mirror of
https://github.com/NishiOwO/ncsa-httpd.git
synced 2025-04-21 08:44:40 +00:00
NCSA HTTPd 1.2
This commit is contained in:
parent
9572b626b7
commit
346064ddbf
109
README
109
README
@ -1,15 +1,37 @@
|
||||
|
||||
NCSA httpd 1.2 is now available via anonymous FTP from
|
||||
ftp://ftp.ncsa.uiuc.edu/Web/ncsa_httpd/current. Note that there is no
|
||||
longer a binary distributed for the DECstation MIPS machines running
|
||||
Ultrix as our DECstation 5000 died and it hasn't been fixed as of yet.
|
||||
|
||||
Documentation for httpd has been moved online. See the URL
|
||||
<A HREF="http://hoohoo.ncsa.uiuc.edu/">here</A> for online hypertext
|
||||
documentation including installation instructions, feature list,
|
||||
demonstration, etc.
|
||||
NCSA httpd is an HTTP/1.0 compatible server for hypermedia documents.
|
||||
It runs on a plethora of UNIX systems. NCSA httpd is also compatible
|
||||
with the Common Gateway Interface which allows interactive document
|
||||
generation.
|
||||
|
||||
Documentation can also be found where you found this .tar file, in a file
|
||||
called httpd_docs.tar.Z.
|
||||
All of the documentation for NCSA httpd is online hypertext. See
|
||||
http://hoohoo.ncsa.uiuc.edu/. If you cannot use a networked WWW browser to
|
||||
read it, retrieve the file /Web/ncsa_httpd/current/httpd_docs.tar.Z from
|
||||
ftp.ncsa.uiuc.edu and use your WWW browser in local only mode to get things
|
||||
started.
|
||||
|
||||
--Rob, Marc, and Eric httpd@ncsa.uiuc.edu
|
||||
Note that the new features introduced with this release required some
|
||||
internal restructuring of the code. This may cause some bugs. If you
|
||||
are pleased with your current setup and do not need the new features
|
||||
you may consider waiting before upgrading in order to make sure that
|
||||
any problems (we expect none, but who ever does?) are worked out prior
|
||||
to your upgrade.
|
||||
|
||||
By popular demand I have written a number of tutorials about various
|
||||
aspects of NCSA httpd configuration. See
|
||||
http://hoohoo.ncsa.uiuc.edu/docs/tutorials/ for an index.
|
||||
|
||||
Thanks all
|
||||
--Rob and Eric
|
||||
|
||||
httpd@ncsa.uiuc.edu
|
||||
|
||||
----
|
||||
|
||||
This code is in the public domain. Specifically, we give to the public
|
||||
domain all rights for future licensing of the source code, all resale
|
||||
@ -26,3 +48,76 @@ FOR THE SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT
|
||||
LIMITATION, WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A
|
||||
PARTICULAR PURPOSE.
|
||||
|
||||
----
|
||||
|
||||
All of the following information is available at
|
||||
http://hoohoo.ncsa.uiuc.edu/docs/Upgrade.html in hypertext form. You
|
||||
should probably read that instead of this primitive plaintext.
|
||||
|
||||
New features
|
||||
|
||||
* The CGI interface is now revised to version 1.1.
|
||||
|
||||
* A new logfile format was agreed upon which should simplify the
|
||||
lives of the authors of logfile analyzers if commonly adopted.
|
||||
|
||||
* CGI scripts are now allowed anywhere.
|
||||
|
||||
* The server side includes interface has been completely
|
||||
rewritten. It is NOT compatible with your old INC SRV documents
|
||||
but a filter is provided to transform your old documents into
|
||||
the new format.
|
||||
|
||||
* There is a new access control option to disable symbolic links
|
||||
only if the owner of the pointer is not the same as the
|
||||
owner of that which is pointed to. This means your users can
|
||||
have symbolic links to things they own, but not to dangerous
|
||||
things like /etc.
|
||||
|
||||
* A new access control method called mutual-failure has been
|
||||
added. This method is a bit unorthodox, but allows
|
||||
you to allow hosts from one domain while excluding certain hosts
|
||||
(such as public access machines) from that domain.
|
||||
|
||||
* Wildcard expressions are now allowed in various areas of server
|
||||
configuration, to allow patterns to be specified. This is most
|
||||
useful in the Directory directive.
|
||||
|
||||
* Directory indexing has been revamped. It looks much different,
|
||||
and I've written a short tutorial on how to set it up.
|
||||
|
||||
* Access Control Files now allow the indexing directives as well
|
||||
as the DefaultType directive.
|
||||
|
||||
* require user now allows quotes for PGP usernames with spaces.
|
||||
|
||||
* Server now explicitly kills CGI scripts when the client aborts
|
||||
or upon timeout
|
||||
|
||||
* Server now verifies the DNS hostname it gets from the IP number
|
||||
to prevent PTR spoofs.
|
||||
|
||||
* Support for 304 and If-modified-since.
|
||||
|
||||
* Support for CGI PUT and DELETE scripts. This will become
|
||||
important later for group annotation features.
|
||||
|
||||
Bug fixes
|
||||
|
||||
All of the known bugs in 1.1 have now been fixed. Now it's time to
|
||||
find the ones I introduce with 1.2.
|
||||
|
||||
* Fixed problem running scripts in ServerMode inetd under IRIX.
|
||||
|
||||
* Fixed bad port problem under OSF/1.
|
||||
|
||||
* Inserted missing return statement for the IdentityCheck directive.
|
||||
|
||||
* Fixed problem whereby errors would stop being logged after a restart.
|
||||
|
||||
* Fixed 256 character limitation on CGI URLs.
|
||||
|
||||
* Access control fix from 1.1 integrated but moved in order to
|
||||
allow certain CGI scripts to continue functioning.
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
DATE=`which date`
|
||||
DATE=/bin/date
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
FINGER=`which finger`
|
||||
FINGER=/usr/ucb/finger
|
||||
|
||||
echo Content-type: text/html
|
||||
echo
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
FORTUNE=`which fortune`
|
||||
FORTUNE=/usr/games/fortune
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
BIN
cgi-bin/imagemap
BIN
cgi-bin/imagemap
Binary file not shown.
@ -9,7 +9,6 @@ echo
|
||||
echo argc is $#. argv is "$*".
|
||||
echo
|
||||
|
||||
echo PATH = $PATH
|
||||
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
|
||||
echo SERVER_NAME = $SERVER_NAME
|
||||
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
|
||||
@ -17,10 +16,10 @@ echo SERVER_PROTOCOL = $SERVER_PROTOCOL
|
||||
echo SERVER_PORT = $SERVER_PORT
|
||||
echo REQUEST_METHOD = $REQUEST_METHOD
|
||||
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
|
||||
echo PATH_INFO = $PATH_INFO
|
||||
echo PATH_TRANSLATED = $PATH_TRANSLATED
|
||||
echo SCRIPT_NAME = $SCRIPT_NAME
|
||||
echo QUERY_STRING = $QUERY_STRING
|
||||
echo PATH_INFO = "$PATH_INFO"
|
||||
echo PATH_TRANSLATED = "$PATH_TRANSLATED"
|
||||
echo SCRIPT_NAME = "$SCRIPT_NAME"
|
||||
echo QUERY_STRING = "$QUERY_STRING"
|
||||
echo REMOTE_HOST = $REMOTE_HOST
|
||||
echo REMOTE_ADDR = $REMOTE_ADDR
|
||||
echo REMOTE_USER = $REMOTE_USER
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
UPTIME=`which uptime`
|
||||
UPTIME=/usr/ucb/uptime
|
||||
|
||||
echo Content-type: text/plain
|
||||
echo
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# wais.pl -- WAIS search interface
|
||||
#
|
||||
# wais.pl,v 1.1 1993/12/31 09:30:56 robm Exp
|
||||
# wais.pl,v 1.2 1994/04/10 05:33:29 robm Exp
|
||||
#
|
||||
# Tony Sanders <sanders@bsdi.com>, Nov 1993
|
||||
#
|
||||
@ -84,4 +84,5 @@ sub docdone {
|
||||
$score = $headline = $lines = $bytes = $type = $date = '';
|
||||
}
|
||||
|
||||
open (STDERR,"> /dev/null");
|
||||
eval '&do_wais';
|
||||
|
@ -57,5 +57,5 @@ change-passwd: change-passwd.o util.o
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o ../cgi-bin/post-query ../cgi-bin/query ../cgi-bin/change-passwd ../cgi-bin/phf ../cgi-bin/jj
|
||||
rm -f *.o ../cgi-bin/post-query ../cgi-bin/query ../cgi-bin/change-passwd ../cgi-bin/phf ../cgi-bin/jj ../cgi-bin/imagemap
|
||||
|
||||
|
@ -31,7 +31,7 @@ int isname(char);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char input[MAXLINE], *mapname, def[MAXLINE], conf[80];
|
||||
char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE];
|
||||
double testpoint[2], pointarray[MAXVERTS][2];
|
||||
int i, j, k;
|
||||
FILE *fp;
|
||||
@ -63,11 +63,11 @@ int main(int argc, char **argv)
|
||||
confname[i] = input[i];
|
||||
confname[i] = '\0';
|
||||
if(!strcmp(confname,mapname))
|
||||
break;
|
||||
goto found;
|
||||
}
|
||||
if(feof(fp))
|
||||
servererr("Map not found in configuration file.");
|
||||
|
||||
found:
|
||||
fclose(fp);
|
||||
while(isspace(input[i]) || input[i] == ':') ++i;
|
||||
|
||||
|
@ -178,11 +178,17 @@ main(int argc, char *argv[]) {
|
||||
strcpy(commandstr, "/usr/local/bin/ph -m ");
|
||||
if (strlen(serverstr)) {
|
||||
strcat(commandstr, " -s ");
|
||||
/* RM 2/22/94 oops */
|
||||
escape_shell_cmd(serverstr);
|
||||
strcat(commandstr, serverstr);
|
||||
strcat(commandstr, " ");
|
||||
}
|
||||
escape_shell_cmd(typestr);
|
||||
strcat(commandstr, typestr);
|
||||
if (atleastonereturn) strcat(commandstr, returnstr);
|
||||
if (atleastonereturn) {
|
||||
escape_shell_cmd(returnstr);
|
||||
strcat(commandstr, returnstr);
|
||||
}
|
||||
|
||||
printf("%s%c", commandstr, LF);
|
||||
printf("<PRE>%c", LF);
|
||||
|
@ -120,3 +120,28 @@ void send_fd(FILE *f, FILE *fd)
|
||||
fputc(c,fd);
|
||||
}
|
||||
}
|
||||
|
||||
int ind(char *s, char c) {
|
||||
register int x;
|
||||
|
||||
for(x=0;s[x];x++)
|
||||
if(s[x] == c) return x;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void escape_shell_cmd(char *cmd) {
|
||||
register int x,y,l;
|
||||
|
||||
l=strlen(cmd);
|
||||
for(x=0;cmd[x];x++) {
|
||||
if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
|
||||
for(y=l+1;y>x;y--)
|
||||
cmd[y] = cmd[y-1];
|
||||
l++; /* length has been increased */
|
||||
cmd[x] = '\\';
|
||||
x++; /* skip the character */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,12 @@ TransferLog logs/access_log
|
||||
PidFile logs/httpd.pid
|
||||
|
||||
# ServerName allows you to set a host name which is sent back to clients for
|
||||
#your server if it's different than the one the program would get (i.e. use
|
||||
#"www" instead of the host's real name).
|
||||
# your server if it's different than the one the program would get (i.e. use
|
||||
# "www" instead of the host's real name).
|
||||
#
|
||||
# Note: You cannot just invent host names and hope they work. The name you
|
||||
# define here must be a valid DNS name for your host. If you don't understand
|
||||
# this, ask your network administrator.
|
||||
|
||||
#ServerName new.host.name
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
# With this document, you define the name space that users see of your http
|
||||
# server.
|
||||
|
||||
# See the tutorials at http://hoohoo.ncsa.uiuc.edu/docs/tutorials/ for
|
||||
# more information.
|
||||
|
||||
# Rob (robm@ncsa.uiuc.edu)
|
||||
|
||||
|
||||
@ -27,13 +30,15 @@ FancyIndexing on
|
||||
# AddIcon tells the server which icon to show for different files or filename
|
||||
# extensions
|
||||
|
||||
AddIcon /icons/text.xbm .html .txt
|
||||
AddIcon /icons/image.xbm .gif .jpg .xbm .tiff
|
||||
AddIcon /icons/sound.xbm .au
|
||||
AddIcon /icons/movie.xbm .mpg
|
||||
AddIconByType (TXT,/icons/text.xbm) text/*
|
||||
AddIconByType (IMG,/icons/image.xbm) image/*
|
||||
AddIconByType (SND,/icons/sound.xbm) audio/*
|
||||
AddIcon /icons/movie.xbm .mpg .qt
|
||||
AddIcon /icons/binary.xbm .bin
|
||||
|
||||
AddIcon /icons/back.xbm ..
|
||||
AddIcon /icons/menu.xbm **DIRECTORY**
|
||||
AddIcon /icons/menu.xbm ^^DIRECTORY^^
|
||||
AddIcon /icons/blank.xbm ^^BLANKICON^^
|
||||
|
||||
# DefaultIcon is which icon to show for files which do not have an icon
|
||||
# explicitly set.
|
||||
@ -49,13 +54,17 @@ DefaultIcon /icons/unknown.xbm
|
||||
#
|
||||
# The server will first look for name.html, include it if found, and it will
|
||||
# then look for name and include it as plaintext if found.
|
||||
#
|
||||
# HeaderName is the name of a file which should be prepended to
|
||||
# directory indexes.
|
||||
|
||||
ReadmeName README
|
||||
HeaderName HEADER
|
||||
|
||||
# IndexIgnore is a set of filenames which directory indexing should ignore
|
||||
# Format: IndexIgnore name1 name2...
|
||||
|
||||
IndexIgnore /.htaccess ~ #
|
||||
IndexIgnore */.??* *~ *# */HEADER* */README*
|
||||
|
||||
# AccessFileName: The name of the file to look for in each directory
|
||||
# for access control information.
|
||||
@ -71,6 +80,12 @@ DefaultType text/plain
|
||||
# make certain files to be certain types.
|
||||
# Format: AddType type/subtype ext1
|
||||
|
||||
# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress
|
||||
# information on the fly. Note: Not all browsers support this.
|
||||
|
||||
#AddEncoding x-compress Z
|
||||
#AddEncoding x-gzip gz
|
||||
|
||||
# Redirect allows you to tell clients about documents which used to exist in
|
||||
# your server's namespace, but do not anymore. This allows you to tell the
|
||||
# clients where to look for the relocated document.
|
||||
@ -86,3 +101,9 @@ Alias /icons/ /usr/local/etc/httpd/icons/
|
||||
# Format: ScriptAlias fakename realname
|
||||
|
||||
ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/
|
||||
|
||||
# If you want to use server side includes, or CGI outside
|
||||
# ScriptAliased directories, uncomment the following lines.
|
||||
|
||||
#AddType text/x-server-parsed-html .shtml
|
||||
#AddType application/x-httpd-cgi .cgi
|
||||
|
9
icons/blank.xbm
Normal file
9
icons/blank.xbm
Normal file
@ -0,0 +1,9 @@
|
||||
#define blank_width 20
|
||||
#define blank_height 23
|
||||
static char blank_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
21
src/Makefile
21
src/Makefile
@ -4,13 +4,13 @@
|
||||
#CC= cc
|
||||
# For Suns or other non-ANSI platforms. Please make sure your gcc is
|
||||
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
|
||||
CC= gcc
|
||||
CC= gcc
|
||||
|
||||
# For optimization
|
||||
#CFLAGS= -O2
|
||||
CFLAGS= -O2
|
||||
# For debugging information
|
||||
#CFLAGS= -g -DPEM_AUTH
|
||||
CFLAGS= -g
|
||||
#CFLAGS= -g -DPEM_AUTH
|
||||
#CFLAGS= -g
|
||||
|
||||
# Place here any extra libraries you may need to link to. You
|
||||
# shouldn't have to.
|
||||
@ -34,7 +34,7 @@ AUX_CFLAGS= -DSUNOS4
|
||||
# For HP-UX
|
||||
#AUX_CFLAGS= -DHPUX
|
||||
# For AIX
|
||||
#AUX_CFLAGS= -DAIX
|
||||
#AUX_CFLAGS= -DAIX -U__STR__
|
||||
# For Ultrix
|
||||
#AUX_CFLAGS= -DULTRIX
|
||||
# For DEC OSF/1
|
||||
@ -47,6 +47,14 @@ AUX_CFLAGS= -DSUNOS4
|
||||
#AUX_CFLAGS= -DLINUX
|
||||
# For A/UX
|
||||
#AUX_CFLAGS= -DAUX
|
||||
# For SCO ODT
|
||||
# libcrypt_i available from sosco.sco.com, files /SLS/lng225b.Z and
|
||||
# /SLS/lng225b.ltr.Z
|
||||
#AUX_CFLAGS= -DSCO
|
||||
#EXTRA_LIBS= -lPW -lsocket -lmalloc -lcrypt_i
|
||||
# For SVR4
|
||||
#AUX_CFLAGS= -DSVR4
|
||||
#EXTRA_LIBS= -lsocket -lnsl -lc
|
||||
|
||||
# Place here any flags you may need upon linking, such as a flag to
|
||||
# prevent dynamic linking (if desired)
|
||||
@ -56,7 +64,8 @@ LFLAGS=
|
||||
|
||||
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
|
||||
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
|
||||
http_get.o http_put.o http_script.o rfc931.o
|
||||
http_get.o http_post.o http_script.o http_include.o rfc931.o \
|
||||
http_put.o http_delete.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<
|
||||
|
100
src/Makefile~
100
src/Makefile~
@ -1,100 +0,0 @@
|
||||
# Makefile for NCSA's httpd.
|
||||
|
||||
# For normal machines with ANSI compilers
|
||||
#CC= cc
|
||||
# For Suns or other non-ANSI platforms. Please make sure your gcc is
|
||||
# 2.0 or later, as 1.40 seems to create bad code for the Sun 4.
|
||||
CC= gcc
|
||||
|
||||
# For optimization
|
||||
#CFLAGS= -O2
|
||||
# For debugging information
|
||||
CFLAGS= -g -DPEM_AUTH
|
||||
#CFLAGS= -g
|
||||
|
||||
# Place here any extra libraries you may need to link to. You
|
||||
# shouldn't have to.
|
||||
EXTRA_LIBS=
|
||||
|
||||
# AUX_CFLAGS are system-specific control flags.
|
||||
# NOTE: IF YOU DO NOT CHOOSE ONE OF THESE, EDIT httpd.h AND CHOOSE
|
||||
# SETTINGS FOR THE SYSTEM FLAGS. IF YOU DON'T, BAD THINGS WILL HAPPEN.
|
||||
|
||||
# For SunOS 4
|
||||
AUX_CFLAGS= -DSUNOS4
|
||||
# For Solaris 2. NOTE: Lots of problems have been identified with compiling
|
||||
# httpd under Solaris. Use with caution. If you see aberrant behavior with
|
||||
# httpd under Solaris 2, please mail us.
|
||||
#AUX_CFLAGS= -DSOLARIS2
|
||||
#EXTRA_LIBS= -lsocket -lnsl
|
||||
# For SGI IRIX. Use the EXTRA_LIBS line if you're using NIS and want
|
||||
# user-supported directories
|
||||
#AUX_CFLAGS= -DIRIX
|
||||
#EXTRA_LIBS= -lsun
|
||||
# For HP-UX
|
||||
#AUX_CFLAGS= -DHPUX
|
||||
# For AIX
|
||||
#AUX_CFLAGS= -DAIX
|
||||
# For Ultrix
|
||||
#AUX_CFLAGS= -DULTRIX
|
||||
# For DEC OSF/1
|
||||
#AUX_CFLAGS= -DOSF1
|
||||
# For NeXT
|
||||
#AUX_CFLAGS= -DNEXT
|
||||
# For Sequent
|
||||
#AUX_CFLAGS= -DSEQUENT
|
||||
# For Linux -m486 ONLY IF YOU HAVE 486 BINARY SUPPORT IN KERNEL
|
||||
#AUX_CFLAGS= -DLINUX
|
||||
# For A/UX
|
||||
#AUX_CFLAGS= -DAUX
|
||||
|
||||
# Place here any flags you may need upon linking, such as a flag to
|
||||
# prevent dynamic linking (if desired)
|
||||
LFLAGS=
|
||||
|
||||
# You shouldn't have to edit anything else.
|
||||
|
||||
OBJS=http_config.o httpd.o http_request.o util.o http_dir.o \
|
||||
http_alias.o http_log.o http_mime.o http_access.o http_auth.o \
|
||||
http_get.o http_put.o http_script.o rfc931.o
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(AUX_CFLAGS) $<
|
||||
|
||||
all: httpd
|
||||
|
||||
ibm:
|
||||
make tar AUX_CFLAGS=-DAIX CC=gcc CFLAGS=-O2
|
||||
|
||||
sun:
|
||||
make tar AUX_CFLAGS=-DSUNOS4 CC=gcc CFLAGS=-O2
|
||||
|
||||
hp:
|
||||
make tar AUX_CFLAGS=-DHPUX CC=gcc CFLAGS=-O2
|
||||
|
||||
sgi:
|
||||
make tar AUX_CFLAGS=-DIRIX EXTRA_LIBS=-lsun CC=cc CFLAGS=-O2
|
||||
|
||||
decmips:
|
||||
make tar AUX_CFLAGS=-DULTRIX CC=cc CFLAGS=-O2
|
||||
|
||||
decaxp:
|
||||
make tar AUX_CFLAGS=-DOSF1 CC=cc CFLAGS=-O2
|
||||
|
||||
httpd: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
purify: $(OBJS)
|
||||
purify -logfile=/X11/robm/httpd/logs/pure_log \
|
||||
-program-name=/X11/robm/httpd/src/httpd \
|
||||
$(CC) $(LFLAGS) -o httpd $(OBJS) $(EXTRA_LIBS)
|
||||
|
||||
tar: $(OBJS)
|
||||
$(CC) $(LFLAGS) -o ../httpd $(OBJS) $(EXTRA_LIBS)
|
||||
rm -f $(OBJS)
|
||||
|
||||
|
||||
$(OBJS): Makefile httpd.h
|
||||
|
||||
clean:
|
||||
rm -f ../httpd httpd $(OBJS) *pure*
|
@ -73,16 +73,17 @@ void check_dir_access(int x, int m, int *w, int *n) {
|
||||
*w=1;
|
||||
if(find_deny(x,m))
|
||||
*w=0;
|
||||
if(sec[x].num_auth[m])
|
||||
*n=x;
|
||||
} else {
|
||||
} else if(sec[x].order[m] == DENY_THEN_ALLOW) {
|
||||
if(find_deny(x,m))
|
||||
*w=0;
|
||||
if(find_allow(x,m))
|
||||
*w=1;
|
||||
if(sec[x].num_auth[m])
|
||||
*n=x;
|
||||
}
|
||||
else
|
||||
*w = find_allow(x,m) && (!find_deny(x,m));
|
||||
|
||||
if(sec[x].num_auth[m])
|
||||
*n=x;
|
||||
}
|
||||
|
||||
void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
|
||||
@ -91,11 +92,14 @@ void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
|
||||
int will_allow, need_auth, num_dirs;
|
||||
char opts[MAX_STRING_LEN], override[MAX_STRING_LEN];
|
||||
char path[MAX_STRING_LEN], d[MAX_STRING_LEN];
|
||||
char errstr[MAX_STRING_LEN];
|
||||
register int x,y,z,n;
|
||||
|
||||
if(S_ISDIR(finfo->st_mode)) strcpy_dir(path,p);
|
||||
else strcpy(path,p);
|
||||
|
||||
no2slash(path);
|
||||
|
||||
num_dirs = count_dirs(path);
|
||||
will_allow=1;need_auth=-1;
|
||||
auth_type=NULL;auth_name=NULL;auth_pwfile=NULL;auth_grpfile=NULL;
|
||||
@ -106,55 +110,101 @@ void evaluate_access(char *p, struct stat *finfo, int m, int *allow,
|
||||
}
|
||||
|
||||
for(x=0;x<num_sec;x++) {
|
||||
if(!strncmp(path,sec[x].d,strlen(sec[x].d))) {
|
||||
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
|
||||
if(!(sec[x].opts & OPT_UNSET))
|
||||
opts[y] = sec[x].opts;
|
||||
override[y] = sec[x].override;
|
||||
if((is_matchexp(path) ? strcmp_match(path,sec[x].d)
|
||||
: !strncmp(path,sec[x].d,strlen(sec[x].d))))
|
||||
{
|
||||
for(y=count_dirs(sec[x].d) - 1;y<num_dirs;y++) {
|
||||
if(!(sec[x].opts & OPT_UNSET))
|
||||
opts[y] = sec[x].opts;
|
||||
override[y] = sec[x].override;
|
||||
}
|
||||
check_dir_access(x,m,&will_allow,&need_auth);
|
||||
}
|
||||
check_dir_access(x,m,&will_allow,&need_auth);
|
||||
}
|
||||
}
|
||||
n=num_dirs-1;
|
||||
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS))) {
|
||||
for(x=0;x<num_dirs;x++) {
|
||||
y = num_sec;
|
||||
make_dirstr(path,x+1,d);
|
||||
if(!(opts[x] & OPT_SYM_LINKS)) {
|
||||
struct stat fi;
|
||||
lstat(d,&fi);
|
||||
if(!(S_ISDIR(fi.st_mode))) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"httpd: will not follow link %s",d);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(override[x]) {
|
||||
parse_htaccess(d,override[x],out);
|
||||
if(num_sec != y) {
|
||||
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
|
||||
if(!(sec[y].opts & OPT_UNSET))
|
||||
opts[z] = sec[y].opts;
|
||||
override[z] = sec[y].override;
|
||||
if((override[n]) || (!(opts[n] & OPT_SYM_LINKS)) ||
|
||||
(opts[n] & OPT_SYM_OWNER))
|
||||
{
|
||||
for(x=0;x<num_dirs;x++) {
|
||||
y = num_sec;
|
||||
make_dirstr(path,x+1,d);
|
||||
if((!(opts[x] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER)) {
|
||||
struct stat lfi,fi;
|
||||
|
||||
lstat(d,&lfi);
|
||||
if(!(S_ISDIR(lfi.st_mode))) {
|
||||
if(opts[x] & OPT_SYM_OWNER) {
|
||||
char realpath[512];
|
||||
int bsz;
|
||||
|
||||
if((bsz = readlink(d,realpath,256)) == -1)
|
||||
goto bong;
|
||||
realpath[bsz] = '\0';
|
||||
if(realpath[0] != '/') {
|
||||
char t[256];
|
||||
strcpy(t,"../");
|
||||
strcpy(&t[3],realpath);
|
||||
make_full_path(d,t,realpath);
|
||||
getparents(realpath);
|
||||
}
|
||||
lstat(realpath,&fi);
|
||||
if(fi.st_uid != lfi.st_uid)
|
||||
goto bong;
|
||||
}
|
||||
else {
|
||||
bong:
|
||||
sprintf(errstr,"httpd: will not follow link %s",d);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(override[x]) {
|
||||
parse_htaccess(d,override[x],out);
|
||||
if(num_sec != y) {
|
||||
for(z=count_dirs(sec[y].d) - 1;z<num_dirs;z++) {
|
||||
if(!(sec[y].opts & OPT_UNSET))
|
||||
opts[z] = sec[y].opts;
|
||||
override[z] = sec[y].override;
|
||||
}
|
||||
check_dir_access(y,m,&will_allow,&need_auth);
|
||||
}
|
||||
check_dir_access(y,m,&will_allow,&need_auth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if((!(S_ISDIR(finfo->st_mode))) && (!(opts[n] & OPT_SYM_LINKS))) {
|
||||
struct stat fi;
|
||||
if((!(S_ISDIR(finfo->st_mode))) &&
|
||||
((!(opts[n] & OPT_SYM_LINKS)) || (opts[x] & OPT_SYM_OWNER))) {
|
||||
struct stat fi,lfi;
|
||||
lstat(path,&fi);
|
||||
if(!(S_ISREG(fi.st_mode))) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"httpd: will not follow link %s",path);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
if(opts[n] & OPT_SYM_OWNER) {
|
||||
char realpath[512];
|
||||
int bsz;
|
||||
|
||||
if((bsz = readlink(path,realpath,256)) == -1)
|
||||
goto gong;
|
||||
realpath[bsz] = '\0';
|
||||
if(realpath[0] != '/') {
|
||||
char t[256];
|
||||
strcpy(t,"../");
|
||||
strcpy(&t[3],realpath);
|
||||
make_full_path(path,t,realpath);
|
||||
getparents(realpath);
|
||||
}
|
||||
lstat(realpath,&lfi);
|
||||
if(fi.st_uid != lfi.st_uid)
|
||||
goto gong;
|
||||
}
|
||||
else {
|
||||
gong:
|
||||
sprintf(errstr,"httpd: will not follow link %s",path);
|
||||
log_error(errstr);
|
||||
*allow=0;
|
||||
*allow_options = OPT_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
*allow = will_allow;
|
||||
@ -179,6 +229,14 @@ void kill_security() {
|
||||
for(y=0;y<sec[x].num_auth[m];y++)
|
||||
free(sec[x].auth[m][y]);
|
||||
}
|
||||
if(sec[x].auth_type)
|
||||
free(sec[x].auth_type);
|
||||
if(sec[x].auth_name)
|
||||
free(sec[x].auth_name);
|
||||
if(sec[x].auth_pwfile)
|
||||
free(sec[x].auth_pwfile);
|
||||
if(sec[x].auth_grpfile)
|
||||
free(sec[x].auth_grpfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ void check_auth(security_data *sec, int m, FILE *out) {
|
||||
char t[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
char errstr[MAX_STRING_LEN];
|
||||
register int x;
|
||||
register int x,y;
|
||||
int grpstatus;
|
||||
|
||||
if(!auth_type) {
|
||||
@ -81,7 +81,7 @@ void check_auth(security_data *sec, int m, FILE *out) {
|
||||
uudecode(t,(unsigned char *)ad,MAX_STRING_LEN);
|
||||
getword(user,ad,':');
|
||||
strcpy(sent_pw,ad);
|
||||
if(!get_pw(user,real_pw)) {
|
||||
if(!get_pw(user,real_pw,out)) {
|
||||
sprintf(errstr,"user %s not found",user);
|
||||
auth_bong(errstr,out);
|
||||
}
|
||||
@ -134,6 +134,11 @@ void check_auth(security_data *sec, int m, FILE *out) {
|
||||
goto found;
|
||||
if(!strcmp(w,"user")) {
|
||||
while(t[0]) {
|
||||
if(t[0] == '\"') {
|
||||
getword(w,&t[1],'\"');
|
||||
for(y=0;t[y];y++)
|
||||
t[y] = t[y+1];
|
||||
}
|
||||
getword(w,t,' ');
|
||||
if(!strcmp(user,w))
|
||||
goto found;
|
||||
@ -176,7 +181,7 @@ void pem_cleanup(int status, FILE *out) {
|
||||
}
|
||||
}
|
||||
|
||||
int pem_decrypt(int sfd, char *req, FILE **out) {
|
||||
int decrypt_request(int sfd, char *req, FILE **out) {
|
||||
int tfd,nr,pid,p[2],decrypt_fd,pem,pgp;
|
||||
char w[MAX_STRING_LEN],w2[MAX_STRING_LEN];
|
||||
char c;
|
||||
@ -186,9 +191,10 @@ int pem_decrypt(int sfd, char *req, FILE **out) {
|
||||
doing_pem = ENCODING_NONE;
|
||||
if(strcmp(req,"/"))
|
||||
return -1;
|
||||
|
||||
|
||||
pem = !(strcmp(content_type,"application/x-www-pem-request"));
|
||||
pgp = !(strcmp(content_type,"application/x-www-pgp-request"));
|
||||
|
||||
if((!pem) && (!pgp))
|
||||
return -1;
|
||||
|
||||
@ -276,6 +282,7 @@ int pem_decrypt(int sfd, char *req, FILE **out) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
error_log2stderr();
|
||||
if(!(argv0 = strrchr(decrypt,'/')))
|
||||
argv0 = decrypt;
|
||||
else
|
||||
|
@ -35,7 +35,7 @@ char auth_pgp_encrypt[MAX_STRING_LEN];
|
||||
char auth_pgp_entity[MAX_STRING_LEN];
|
||||
#endif
|
||||
|
||||
void process_server_config() {
|
||||
void process_server_config(FILE *errors) {
|
||||
FILE *cfg;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
int n=0;
|
||||
@ -67,7 +67,7 @@ void process_server_config() {
|
||||
#endif
|
||||
|
||||
if(!(cfg = fopen(server_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open server config. file %s\n",server_confname);
|
||||
fprintf(errors,"httpd: could not open server config. file %s\n",server_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
@ -81,8 +81,8 @@ void process_server_config() {
|
||||
if(!strcasecmp(l,"inetd")) standalone=0;
|
||||
else if(!strcasecmp(l,"standalone")) standalone=1;
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"ServerType is either inetd or standalone.\n");
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(errors,"ServerType is either inetd or standalone.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -107,13 +107,13 @@ void process_server_config() {
|
||||
if(server_hostname)
|
||||
free(server_hostname);
|
||||
if(!(server_hostname = strdup(w)))
|
||||
die(NO_MEMORY,"process_resource_config",stderr);
|
||||
die(NO_MEMORY,"process_resource_config",errors);
|
||||
}
|
||||
else if(!strcasecmp(w,"ServerRoot")) {
|
||||
cfg_getword(w,l);
|
||||
if(!is_directory(w)) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"%s is not a valid directory.\n",w);
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(errors,"%s is not a valid directory.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(server_root,w);
|
||||
@ -170,9 +170,9 @@ void process_server_config() {
|
||||
else if(!strcmp(w,"off"))
|
||||
do_rfc931 = 0;
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"IdentityCheck must be on or off.\n");
|
||||
fprintf(errors,"IdentityCheck must be on or off.\n");
|
||||
}
|
||||
}
|
||||
#ifdef PEM_AUTH
|
||||
@ -202,8 +202,8 @@ void process_server_config() {
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(stderr,"Unknown keyword %s.\n",w);
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,server_confname);
|
||||
fprintf(errors,"Unknown keyword %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -218,10 +218,8 @@ char access_name[MAX_STRING_LEN];
|
||||
char document_root[MAX_STRING_LEN];
|
||||
char default_type[MAX_STRING_LEN];
|
||||
char default_icon[MAX_STRING_LEN];
|
||||
int fancy_indexing;
|
||||
char readme_fname[MAX_STRING_LEN];
|
||||
|
||||
void process_resource_config() {
|
||||
void process_resource_config(FILE *errors) {
|
||||
FILE *cfg;
|
||||
char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
|
||||
int n=0;
|
||||
@ -232,11 +230,11 @@ void process_resource_config() {
|
||||
strcpy(document_root,DOCUMENT_LOCATION);
|
||||
strcpy(default_type,DEFAULT_TYPE);
|
||||
default_icon[0] = '\0';
|
||||
fancy_indexing = DEFAULT_INDEXING;
|
||||
readme_fname[0] = '\0';
|
||||
|
||||
add_opts_int(0,"/",errors);
|
||||
|
||||
if(!(cfg = fopen(srm_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open document config. file %s\n",
|
||||
fprintf(errors,"httpd: could not open document config. file %s\n",
|
||||
srm_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
@ -253,9 +251,9 @@ void process_resource_config() {
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -267,9 +265,9 @@ void process_resource_config() {
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"ScriptAlias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -297,9 +295,9 @@ void process_resource_config() {
|
||||
else if(!strcasecmp(w,"DocumentRoot")) {
|
||||
cfg_getword(w,l);
|
||||
if(!is_directory(w)) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"%s is not a valid directory.\n",w);
|
||||
fprintf(errors,"%s is not a valid directory.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(document_root,w);
|
||||
@ -310,9 +308,9 @@ void process_resource_config() {
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"Alias must be followed by a fakename, one space, then a realname.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -323,35 +321,35 @@ void process_resource_config() {
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"AddType must be followed by a type, one space, then a file or extension.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_type(w2,w,stderr);
|
||||
add_type(w2,w,errors);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddEncoding")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0')) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"AddEncoding must be followed by a type, one space, then a file or extension.\n");
|
||||
exit(1);
|
||||
}
|
||||
add_encoding(w2,w,stderr);
|
||||
add_encoding(w2,w,errors);
|
||||
}
|
||||
else if(!strcasecmp(w,"Redirect")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w,l);
|
||||
cfg_getword(w2,l);
|
||||
if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"Redirect must be followed by a document, one space, then a URL.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -360,13 +358,13 @@ void process_resource_config() {
|
||||
else if(!strcasecmp(w,"FancyIndexing")) {
|
||||
cfg_getword(w,l);
|
||||
if(!strcmp(w,"on"))
|
||||
fancy_indexing = 1;
|
||||
add_opts_int(FANCY_INDEXING,"/",errors);
|
||||
else if(!strcmp(w,"off"))
|
||||
fancy_indexing = 0;
|
||||
add_opts_int(0,"/",errors);
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"FancyIndexing must be on or off.\n");
|
||||
fprintf(errors,"FancyIndexing must be on or off.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -374,21 +372,21 @@ void process_resource_config() {
|
||||
char desc[MAX_STRING_LEN];
|
||||
int fq;
|
||||
if((fq = ind(l,'\"')) == -1) {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(stderr,"AddDescription must have quotes around the description.\n");
|
||||
fprintf(errors,"AddDescription must have quotes around the description.\n");
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
getword(desc,&l[++fq],'\"');
|
||||
cfg_getword(w,&l[fq]);
|
||||
add_desc(desc,w,stderr);
|
||||
add_desc(BY_PATH,desc,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexIgnore")) {
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_ignore(w,stderr);
|
||||
add_ignore(w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIcon")) {
|
||||
@ -396,7 +394,47 @@ fprintf(stderr,"AddDescription must have quotes around the description.\n");
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(w2,w,stderr);
|
||||
add_icon(BY_PATH,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIconByType")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(BY_TYPE,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIconByEncoding")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(BY_ENCODING,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddAlt")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_alt(BY_PATH,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddAltByType")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_alt(BY_TYPE,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddAltByEncoding")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_alt(BY_ENCODING,w2,w,"/",errors);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultIcon")) {
|
||||
@ -405,11 +443,18 @@ fprintf(stderr,"AddDescription must have quotes around the description.\n");
|
||||
}
|
||||
else if(!strcasecmp(w,"ReadmeName")) {
|
||||
cfg_getword(w,l);
|
||||
strcpy(readme_fname,w);
|
||||
add_readme(w,"/",errors);
|
||||
}
|
||||
else if(!strcasecmp(w,"HeaderName")) {
|
||||
cfg_getword(w,l);
|
||||
add_header(w,"/",errors);
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexOptions"))
|
||||
add_opts(l,"/",errors);
|
||||
else {
|
||||
fprintf(stderr,"Syntax error on line %d of %s:\n",n,srm_confname);
|
||||
fprintf(stderr,"Unknown keyword %s.\n",w);
|
||||
fprintf(errors,"Syntax error on line %d of %s:\n",n,
|
||||
srm_confname);
|
||||
fprintf(errors,"Unknown keyword %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -430,8 +475,8 @@ security_data sec[MAX_SECURITY];
|
||||
|
||||
void access_syntax_error(int n, char *err, char *file, FILE *out) {
|
||||
if(!file) {
|
||||
fprintf(stderr,"Syntax error on line %d of access config. file.\n",n);
|
||||
fprintf(stderr,"%s\n",err);
|
||||
fprintf(out,"Syntax error on line %d of access config. file.\n",n);
|
||||
fprintf(out,"%s\n",err);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
@ -508,8 +553,14 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
sec[x].opts |= OPT_INDEXES;
|
||||
else if(!strcasecmp(w,"Includes"))
|
||||
sec[x].opts |= OPT_INCLUDES;
|
||||
else if(!strcasecmp(w,"IncludesNOEXEC"))
|
||||
sec[x].opts |= (OPT_INCLUDES | OPT_INCNOEXEC);
|
||||
else if(!strcasecmp(w,"FollowSymLinks"))
|
||||
sec[x].opts |= OPT_SYM_LINKS;
|
||||
else if(!strcasecmp(w,"SymLinksIfOwnerMatch"))
|
||||
sec[x].opts |= OPT_SYM_OWNER;
|
||||
else if(!strcasecmp(w,"execCGI"))
|
||||
sec[x].opts |= OPT_EXECCGI;
|
||||
else if(!strcasecmp(w,"None"))
|
||||
sec[x].opts = OPT_NONE;
|
||||
else if(!strcasecmp(w,"All"))
|
||||
@ -567,6 +618,12 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
}
|
||||
add_type(w2,w,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultType")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_type,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddEncoding")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
@ -579,49 +636,84 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
}
|
||||
add_encoding(w2,w,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddDescription")) {
|
||||
int fq;
|
||||
if(!(or & OR_FILEINFO))
|
||||
else if(!strcasecmp(w,"DefaultIcon")) {
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
if((fq = ind(l,'\"')) == -1) {
|
||||
access_syntax_error(n,
|
||||
"AddDescription must have quotes around the description.\n",
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_icon,w);
|
||||
}
|
||||
else if(!strcasecmp(w,"AddDescription")) {
|
||||
char desc[MAX_STRING_LEN];
|
||||
int fq;
|
||||
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
if((fq = ind(l,'\"')) == -1)
|
||||
access_syntax_error(n,"AddDescription must have quotes",
|
||||
file,out);
|
||||
}
|
||||
else {
|
||||
getword(w2,&l[++fq],'\"');
|
||||
getword(desc,&l[++fq],'\"');
|
||||
cfg_getword(w,&l[fq]);
|
||||
add_desc(w2,w,stderr);
|
||||
add_desc(BY_PATH,desc,w,sec[x].d,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexIgnore")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_ignore(w,out);
|
||||
add_ignore(w,sec[x].d,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIcon")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(w2,w,out);
|
||||
add_icon(BY_PATH,w2,w,sec[x].d,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIconByType")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(BY_TYPE,w2,w,sec[x].d,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"AddIconByEncoding")) {
|
||||
char w2[MAX_STRING_LEN];
|
||||
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w2,l);
|
||||
while(l[0]) {
|
||||
cfg_getword(w,l);
|
||||
add_icon(BY_ENCODING,w2,w,sec[x].d,out);
|
||||
}
|
||||
}
|
||||
else if(!strcasecmp(w,"ReadmeName")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
strcpy(readme_fname,w);
|
||||
add_readme(w,sec[x].d,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"DefaultIcon")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
else if(!strcasecmp(w,"HeaderName")) {
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
cfg_getword(w,l);
|
||||
strcpy(default_icon,w);
|
||||
add_header(w,sec[x].d,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"IndexOptions")) {
|
||||
if(!(or & OR_INDEXES))
|
||||
access_syntax_error(n,"override violation",file,out);
|
||||
add_opts(l,sec[x].d,out);
|
||||
}
|
||||
else if(!strcasecmp(w,"Redirect")) {
|
||||
if(!(or & OR_FILEINFO))
|
||||
@ -650,6 +742,7 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
if(!strcasecmp(w,"GET")) m[M_GET]=1;
|
||||
else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
|
||||
else if(!strcasecmp(w,"POST")) m[M_POST]=1;
|
||||
else if(!strcasecmp(w,"DELETE")) m[M_DELETE]=1;
|
||||
}
|
||||
while(1) {
|
||||
if(cfg_getline(l,MAX_STRING_LEN,f))
|
||||
@ -671,6 +764,11 @@ int parse_access_dir(FILE *f, int line, char or, char *dir,
|
||||
if(m[i])
|
||||
sec[x].order[i] = DENY_THEN_ALLOW;
|
||||
}
|
||||
else if(!strcasecmp(l,"mutual-failure")) {
|
||||
for(i=0;i<METHODS;i++)
|
||||
if(m[i])
|
||||
sec[x].order[i] = MUTUAL_FAILURE;
|
||||
}
|
||||
else
|
||||
access_syntax_error(n,"Unknown order.",file,out);
|
||||
}
|
||||
@ -751,7 +849,7 @@ void parse_htaccess(char *path, char override, FILE *out) {
|
||||
}
|
||||
|
||||
|
||||
void process_access_config() {
|
||||
void process_access_config(FILE *errors) {
|
||||
FILE *f;
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
@ -759,7 +857,7 @@ void process_access_config() {
|
||||
|
||||
num_sec = 0;n=0;
|
||||
if(!(f=fopen(access_confname,"r"))) {
|
||||
fprintf(stderr,"httpd: could not open access configuration file %s.\n",
|
||||
fprintf(errors,"httpd: could not open access configuration file %s.\n",
|
||||
access_confname);
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
@ -769,18 +867,18 @@ void process_access_config() {
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
cfg_getword(w,l);
|
||||
if(strcasecmp(w,"<Directory")) {
|
||||
fprintf(stderr,
|
||||
fprintf(errors,
|
||||
"Syntax error on line %d of access config. file.\n",n);
|
||||
fprintf(stderr,"Unknown directive %s.\n",w);
|
||||
fprintf(errors,"Unknown directive %s.\n",w);
|
||||
exit(1);
|
||||
}
|
||||
getword(w,l,'>');
|
||||
n=parse_access_dir(f,n,OR_ALL,w,NULL,stderr);
|
||||
n=parse_access_dir(f,n,OR_ALL,w,NULL,errors);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int get_pw(char *user, char *pw) {
|
||||
int get_pw(char *user, char *pw, FILE *errors) {
|
||||
FILE *f;
|
||||
char errstr[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
@ -788,7 +886,7 @@ int get_pw(char *user, char *pw) {
|
||||
|
||||
if(!(f=fopen(auth_pwfile,"r"))) {
|
||||
sprintf(errstr,"Could not open user file %s",auth_pwfile);
|
||||
die(SERVER_ERROR,errstr,stdout); /* AAAAAAAAGH stdout */
|
||||
die(SERVER_ERROR,errstr,errors);
|
||||
}
|
||||
while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
|
||||
if((l[0] == '#') || (!l[0])) continue;
|
||||
@ -868,12 +966,12 @@ void kill_group() {
|
||||
}
|
||||
}
|
||||
|
||||
void read_config()
|
||||
void read_config(FILE *errors)
|
||||
{
|
||||
reset_aliases();
|
||||
process_server_config();
|
||||
init_mime();
|
||||
process_server_config(errors);
|
||||
init_mime(errors);
|
||||
init_indexing();
|
||||
process_resource_config();
|
||||
process_access_config();
|
||||
process_resource_config(errors);
|
||||
process_access_config(errors);
|
||||
}
|
||||
|
57
src/http_delete.c
Normal file
57
src/http_delete.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* http_delete.c: Handles DELETE
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
|
||||
void handle_delete(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
char ct_bak[MAX_STRING_LEN];
|
||||
|
||||
if(stat(name,&finfo) == -1) {
|
||||
if(find_script("DELETE",name,args,in,out))
|
||||
return;
|
||||
if(errno==ENOENT) {
|
||||
log_reason("file does not exist",name);
|
||||
unmunge_name(name);
|
||||
die(NOT_FOUND,name,out);
|
||||
}
|
||||
else {
|
||||
log_reason("file permissions deny server access",name);
|
||||
unmunge_name(name);
|
||||
die(FORBIDDEN,name,out);
|
||||
}
|
||||
}
|
||||
probe_content_type(name);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
|
||||
strcpy(content_type,ct_bak);
|
||||
send_cgi("DELETE",name,"",args,&finfo,in,out);
|
||||
return;
|
||||
}
|
||||
/* Not a script, do group ann thang */
|
||||
die(NOT_IMPLEMENTED,"DELETE to non-script",out);
|
||||
}
|
||||
|
||||
|
||||
void delete_node(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
int s;
|
||||
|
||||
s=translate_name(name,out);
|
||||
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
handle_delete(name,args,in,out);
|
||||
return;
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,name,out);
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script("DELETE",name,args,in,out);
|
||||
default:
|
||||
die(NOT_IMPLEMENTED,"NCSA script exeuction of delete",out);
|
||||
}
|
||||
}
|
493
src/http_dir.c
493
src/http_dir.c
@ -13,31 +13,46 @@
|
||||
struct ent {
|
||||
char *name;
|
||||
char *icon;
|
||||
char *alt;
|
||||
char *desc;
|
||||
size_t size;
|
||||
time_t lm;
|
||||
struct ent *next;
|
||||
};
|
||||
|
||||
|
||||
struct item {
|
||||
char *msg;
|
||||
char *fn;
|
||||
int type;
|
||||
char *apply_to;
|
||||
char *apply_path;
|
||||
char *data;
|
||||
struct item *next;
|
||||
};
|
||||
|
||||
static struct item *icon_list, *desc_list, *ign_list;
|
||||
|
||||
static struct item *icon_list, *alt_list, *desc_list, *ign_list;
|
||||
static struct item *hdr_list, *rdme_list, *opts_list;
|
||||
|
||||
static int dir_opts;
|
||||
|
||||
void init_indexing() {
|
||||
icon_list = NULL;
|
||||
alt_list = NULL;
|
||||
desc_list = NULL;
|
||||
ign_list = NULL;
|
||||
|
||||
hdr_list = NULL;
|
||||
rdme_list = NULL;
|
||||
opts_list = NULL;
|
||||
}
|
||||
|
||||
void kill_item_list(struct item *p) {
|
||||
struct item *q;
|
||||
|
||||
while(p) {
|
||||
if(p->msg) free(p->msg);
|
||||
if(p->fn) free(p->fn);
|
||||
if(p->apply_to) free(p->apply_to);
|
||||
if(p->apply_path) free(p->apply_path);
|
||||
if(p->data) free(p->data);
|
||||
q = p;
|
||||
p = p->next;
|
||||
free(q);
|
||||
@ -46,202 +61,444 @@ void kill_item_list(struct item *p) {
|
||||
|
||||
void kill_indexing() {
|
||||
kill_item_list(icon_list);
|
||||
kill_item_list(alt_list);
|
||||
kill_item_list(desc_list);
|
||||
kill_item_list(ign_list);
|
||||
|
||||
kill_item_list(hdr_list);
|
||||
kill_item_list(rdme_list);
|
||||
kill_item_list(opts_list);
|
||||
}
|
||||
|
||||
void add_icon(char *icon, char *ext, FILE *out) {
|
||||
struct item *new_item(int type, char *to, char *path, char *data, FILE *out)
|
||||
{
|
||||
struct item *p;
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
if(!(p->msg = strdup(icon)))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_icon",out);
|
||||
die(NO_MEMORY,"new_item",out);
|
||||
|
||||
p->type = type;
|
||||
if(data) {
|
||||
if(!(p->data = strdup(data)))
|
||||
die(NO_MEMORY,"new_item",out);
|
||||
} else
|
||||
p->data = NULL;
|
||||
|
||||
if(to) {
|
||||
if(!(p->apply_to = (char *)malloc(strlen(to) + 2)))
|
||||
die(NO_MEMORY,"new_item",out);
|
||||
if((type == BY_PATH) && (!is_matchexp(to))) {
|
||||
p->apply_to[0] = '*';
|
||||
strcpy(&p->apply_to[1],to);
|
||||
} else
|
||||
strcpy(p->apply_to,to);
|
||||
} else
|
||||
p->apply_to = NULL;
|
||||
|
||||
if(!(p->apply_path = (char *)malloc(strlen(path) + 2)))
|
||||
die(NO_MEMORY,"new_item",out);
|
||||
sprintf(p->apply_path,"%s*",path);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void add_alt(int type, char *alt, char *to, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
if(type == BY_PATH) {
|
||||
if(!strcmp(to,"**DIRECTORY**"))
|
||||
strcpy(to,"^^DIRECTORY^^");
|
||||
}
|
||||
p = new_item(type,to,path,alt,out);
|
||||
p->next = alt_list;
|
||||
alt_list = p;
|
||||
}
|
||||
|
||||
void add_icon(int type, char *icon, char *to, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
char iconbak[MAX_STRING_LEN];
|
||||
|
||||
strcpy(iconbak,icon);
|
||||
if(icon[0] == '(') {
|
||||
char alt[MAX_STRING_LEN];
|
||||
getword(alt,iconbak,',');
|
||||
add_alt(type,&alt[1],to,path,out);
|
||||
iconbak[strlen(iconbak) - 1] = '\0';
|
||||
}
|
||||
if(type == BY_PATH) {
|
||||
if(!strcmp(to,"**DIRECTORY**"))
|
||||
strcpy(to,"^^DIRECTORY^^");
|
||||
}
|
||||
p = new_item(type,to,path,iconbak,out);
|
||||
p->next = icon_list;
|
||||
icon_list = p;
|
||||
}
|
||||
|
||||
char *find_icon(char *path) {
|
||||
struct item *p = icon_list;
|
||||
int pl, el;
|
||||
|
||||
pl = strlen(path);
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
return p->msg;
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_desc(char *desc, char *ext, FILE *out) {
|
||||
void add_desc(int type, char *desc, char *to, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
if(!(p->msg = strdup(desc)))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_desc",out);
|
||||
p = new_item(type,to,path,desc,out);
|
||||
p->next = desc_list;
|
||||
desc_list = p;
|
||||
}
|
||||
|
||||
char *find_desc(char *path) {
|
||||
struct item *p = desc_list;
|
||||
int pl, el;
|
||||
void add_ignore(char *ext, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
p = new_item(0,ext,path,NULL,out);
|
||||
p->next = ign_list;
|
||||
ign_list = p;
|
||||
}
|
||||
|
||||
void add_header(char *name, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
p = new_item(0,NULL,path,name,out);
|
||||
p->next = hdr_list;
|
||||
hdr_list = p;
|
||||
}
|
||||
|
||||
void add_readme(char *name, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
p = new_item(0,NULL,path,name,out);
|
||||
p->next = rdme_list;
|
||||
rdme_list = p;
|
||||
}
|
||||
|
||||
|
||||
void add_opts_int(int opts, char *path, FILE *out) {
|
||||
struct item *p;
|
||||
|
||||
p = new_item(0,NULL,path,NULL,out);
|
||||
p->type = opts;
|
||||
p->next = opts_list;
|
||||
opts_list = p;
|
||||
}
|
||||
|
||||
void add_opts(char *optstr, char *path, FILE *out) {
|
||||
char w[MAX_STRING_LEN];
|
||||
int opts = 0;
|
||||
|
||||
while(optstr[0]) {
|
||||
cfg_getword(w,optstr);
|
||||
if(!strcasecmp(w,"FancyIndexing"))
|
||||
opts |= FANCY_INDEXING;
|
||||
else if(!strcasecmp(w,"IconsAreLinks"))
|
||||
opts |= ICONS_ARE_LINKS;
|
||||
else if(!strcasecmp(w,"ScanHTMLTitles"))
|
||||
opts |= SCAN_HTML_TITLES;
|
||||
else if(!strcasecmp(w,"None"))
|
||||
opts = 0;
|
||||
}
|
||||
add_opts_int(opts,path,out);
|
||||
}
|
||||
|
||||
|
||||
char *find_item(struct item *list, char *path, int path_only) {
|
||||
struct item *p = list;
|
||||
char *t;
|
||||
|
||||
pl = strlen(path);
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
return p->msg;
|
||||
/* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
|
||||
if((path[0] == '^') || (!strcmp_match(path,p->apply_path))) {
|
||||
if(!(p->apply_to))
|
||||
return p->data;
|
||||
else if(p->type == BY_PATH) {
|
||||
if(!strcmp_match(path,p->apply_to))
|
||||
return p->data;
|
||||
} else if(!path_only) {
|
||||
char pathbak[MAX_STRING_LEN];
|
||||
|
||||
strcpy(pathbak,path);
|
||||
content_encoding[0] = '\0';
|
||||
set_content_type(pathbak);
|
||||
if(!content_encoding[0]) {
|
||||
if(p->type == BY_TYPE) {
|
||||
if(!strcmp_match(content_type,p->apply_to))
|
||||
return p->data;
|
||||
}
|
||||
} else {
|
||||
if(p->type == BY_ENCODING) {
|
||||
if(!strcmp_match(content_encoding,p->apply_to))
|
||||
return p->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_ignore(char *ext,FILE *out) {
|
||||
struct item *p;
|
||||
#define find_icon(p,t) find_item(icon_list,p,t)
|
||||
#define find_alt(p) find_item(alt_list,p,0)
|
||||
#define find_desc(p) find_item(desc_list,p,0)
|
||||
#define find_header(p) find_item(hdr_list,p,0)
|
||||
#define find_readme(p) find_item(rdme_list,p,0)
|
||||
|
||||
if(!(p = (struct item *)malloc(sizeof(struct item))))
|
||||
die(NO_MEMORY,"add_ignore",out);
|
||||
p->msg = NULL;
|
||||
if(!(p->fn = strdup(ext)))
|
||||
die(NO_MEMORY,"add_ignore",out);
|
||||
p->next = ign_list;
|
||||
ign_list = p;
|
||||
}
|
||||
|
||||
int ignore_entry(char *path) {
|
||||
struct item *p;
|
||||
int pl,el;
|
||||
struct item *p = ign_list;
|
||||
|
||||
pl = strlen(path);
|
||||
p = ign_list;
|
||||
while(p) {
|
||||
el = strlen(p->fn);
|
||||
if(el <= pl)
|
||||
if(!strcmp(&path[pl - el],p->fn))
|
||||
if(!strcmp_match(path,p->apply_path))
|
||||
if(!strcmp_match(path,p->apply_to))
|
||||
return 1;
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void insert_readme(char *name, FILE *fd) {
|
||||
int find_opts(char *path) {
|
||||
struct item *p = opts_list;
|
||||
|
||||
while(p) {
|
||||
if(!strcmp_match(path,p->apply_path))
|
||||
return p->type;
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int insert_readme(char *name, char *readme_fname, int rule, FILE *fd) {
|
||||
char fn[MAX_STRING_LEN];
|
||||
FILE *r;
|
||||
struct stat finfo;
|
||||
int plaintext=0;
|
||||
|
||||
if(!readme_fname[0])
|
||||
return;
|
||||
make_full_path(name,readme_fname,fn);
|
||||
strcat(fn,".html");
|
||||
if(stat(fn,&finfo) == -1) {
|
||||
fn[strlen(fn)-5] = '\0';
|
||||
if(stat(fn,&finfo) == -1)
|
||||
return;
|
||||
return 0;
|
||||
plaintext=1;
|
||||
fprintf(fd,"<HR><PRE>%c",LF);
|
||||
if(rule) bytes_sent += fprintf(fd,"<HR>%c",LF);
|
||||
bytes_sent += fprintf(fd,"<PRE>%c",LF);
|
||||
}
|
||||
else fprintf(fd,"<HR>");
|
||||
else if(rule) bytes_sent += fprintf(fd,"<HR>%c",LF);
|
||||
if(!(r = fopen(fn,"r")))
|
||||
return;
|
||||
send_fd(r,fd,"");
|
||||
return 0;
|
||||
send_fd(r,fd,NULL);
|
||||
fclose(r);
|
||||
if(plaintext)
|
||||
fprintf(fd,"</PRE>%c",LF);
|
||||
bytes_sent += fprintf(fd,"</PRE>%c",LF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *find_title(char *filename) {
|
||||
char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
|
||||
char filebak[MAX_STRING_LEN];
|
||||
FILE *thefile;
|
||||
int x,n,p;
|
||||
|
||||
content_encoding[0] = '\0';
|
||||
strcpy(filebak,filename);
|
||||
set_content_type(filebak);
|
||||
if((!strcmp(content_type,"text/html")) && (!content_encoding[0])) {
|
||||
if(!(thefile = fopen(filename,"r")))
|
||||
return NULL;
|
||||
n = fread(titlebuf,sizeof(char),MAX_STRING_LEN - 1,thefile);
|
||||
titlebuf[n] = '\0';
|
||||
for(x=0,p=0;titlebuf[x];x++) {
|
||||
if(titlebuf[x] == find[p]) {
|
||||
if(!find[++p]) {
|
||||
if((p = ind(&titlebuf[++x],'<')) != -1)
|
||||
titlebuf[x+p] = '\0';
|
||||
return strdup(&titlebuf[x]);
|
||||
}
|
||||
} else p=0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
content_encoding[0] = '\0';
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ent *make_dir_entry(char *path, char *name, FILE *out) {
|
||||
struct ent *p;
|
||||
struct stat finfo;
|
||||
char t[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN], t2[MAX_STRING_LEN];
|
||||
|
||||
if((name[0] == '.') && (!name[1]))
|
||||
return(NULL);
|
||||
|
||||
make_full_path(path,name,t);
|
||||
|
||||
if(ignore_entry(t))
|
||||
return(NULL);
|
||||
|
||||
if(!(p=(struct ent *)malloc(sizeof(struct ent))))
|
||||
die(NO_MEMORY,"make_dir_entry",out);
|
||||
if(!(p->name=strdup(name)))
|
||||
if(!(p->name=(char *)malloc(strlen(name) + 2)))
|
||||
die(NO_MEMORY,"make_dir_entry",out);
|
||||
|
||||
if(fancy_indexing) {
|
||||
p->icon = find_icon(t);
|
||||
if((!fancy_indexing) || stat(t,&finfo) == -1) {
|
||||
if(dir_opts & FANCY_INDEXING) {
|
||||
p->alt = find_alt(t);
|
||||
if((!(dir_opts & FANCY_INDEXING)) || stat(t,&finfo) == -1) {
|
||||
strcpy(p->name,name);
|
||||
p->size = -1;
|
||||
p->icon = NULL;
|
||||
p->desc = NULL;
|
||||
p->lm = -1;
|
||||
}
|
||||
else {
|
||||
p->lm = finfo.st_mtime;
|
||||
if(S_ISDIR(finfo.st_mode)) {
|
||||
if(!p->icon)
|
||||
p->icon = find_icon("**DIRECTORY**");
|
||||
if(!(p->icon = find_icon(t,1)))
|
||||
p->icon = find_icon("^^DIRECTORY^^",1);
|
||||
p->alt = "DIR";
|
||||
p->size = -1;
|
||||
strcpy_dir(p->name,name);
|
||||
}
|
||||
else
|
||||
else {
|
||||
p->icon = find_icon(t,0);
|
||||
p->size = finfo.st_size;
|
||||
strcpy(p->name,name);
|
||||
}
|
||||
}
|
||||
p->desc = find_desc(t);
|
||||
if(p->desc = find_desc(t))
|
||||
p->desc = strdup(p->desc);
|
||||
if((!p->desc) && (dir_opts & SCAN_HTML_TITLES))
|
||||
p->desc = find_title(t);
|
||||
}
|
||||
else {
|
||||
p->icon = NULL;
|
||||
p->alt = NULL;
|
||||
p->desc = NULL;
|
||||
p->size = -1;
|
||||
p->lm = -1;
|
||||
strcpy(p->name,name);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
|
||||
void send_size(size_t size, FILE *fd) {
|
||||
char schar;
|
||||
|
||||
if(size == -1) {
|
||||
fputs(" -",fd);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
else {
|
||||
if(!size) {
|
||||
fputs(" 0K",fd);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
else if(size < 1024) {
|
||||
fputs(" 1K",fd);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
else if(size < 1048576)
|
||||
bytes_sent += fprintf(fd,"%4dK",size / 1024);
|
||||
else
|
||||
bytes_sent += fprintf(fd,"%4dM",size / 1048576);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void output_directories(struct ent **ar,int n,char *name,FILE *fd)
|
||||
{
|
||||
int x;
|
||||
char blorf[MAX_STRING_LEN];
|
||||
int x,pad;
|
||||
char anchor[HUGE_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
|
||||
char *tp;
|
||||
|
||||
if(name[0] == '\0') {
|
||||
name[0] = '/'; name[1] = '\0';
|
||||
}
|
||||
/* aaaaargh Solaris sucks. */
|
||||
fflush(fd);
|
||||
|
||||
if(dir_opts & FANCY_INDEXING) {
|
||||
fputs("<PRE>",fd);
|
||||
bytes_sent += 5;
|
||||
if(tp = find_icon("^^BLANKICON^^",1))
|
||||
bytes_sent += fprintf(fd,"<IMG SRC=\"%s\" ALT=\" \"> ",tp);
|
||||
bytes_sent += fprintf(fd,
|
||||
"Name Last modified Size Description%c<HR>%c",LF,LF);
|
||||
}
|
||||
else {
|
||||
fputs("<UL>",fd);
|
||||
bytes_sent += 4;
|
||||
}
|
||||
|
||||
for(x=0;x<n;x++) {
|
||||
fprintf(fd,"<%s>%c",(fancy_indexing ? "DD" : "LI"),LF);
|
||||
if(fancy_indexing && ((ar[x]->icon) || default_icon[0])) {
|
||||
fprintf(fd,"<IMG SRC=\"%s\"> ",
|
||||
ar[x]->icon ? ar[x]->icon : default_icon);
|
||||
}
|
||||
if(strcmp(ar[x]->name,"..")) {
|
||||
make_full_path(name,ar[x]->name,blorf);
|
||||
escape_url(blorf);
|
||||
fprintf(fd,"<A NAME=\"%s\" HREF=\"%s\">%s</A>",ar[x]->name,
|
||||
blorf,ar[x]->name);
|
||||
if((!strcmp(ar[x]->name,"../")) || (!strcmp(ar[x]->name,".."))) {
|
||||
make_full_path(name,"..",t);
|
||||
getparents(t);
|
||||
if(t[0] == '\0') {
|
||||
t[0] = '/'; t[1] = '\0';
|
||||
}
|
||||
sprintf(anchor,"<A HREF=\"%s\">",t);
|
||||
strcpy(t2,"Parent Directory</A>");
|
||||
}
|
||||
else {
|
||||
make_full_path(name,"..",blorf);
|
||||
getparents(blorf);
|
||||
if(blorf[0] == '\0') {
|
||||
blorf[0] = '/'; blorf[1] = '\0';
|
||||
strcpy(t,ar[x]->name);
|
||||
strcpy(t2,t);
|
||||
if(strlen(t2) > 21) {
|
||||
t2[21] = '>';
|
||||
t2[22] = '\0';
|
||||
}
|
||||
escape_url(blorf);
|
||||
fprintf(fd,"<A HREF=\"%s\">%s</A>",blorf,"Parent Directory");
|
||||
strcat(t2,"</A>");
|
||||
escape_url(t);
|
||||
sprintf(anchor,"<A NAME=\"%s\" HREF=\"%s\">",t,t);
|
||||
}
|
||||
if(fancy_indexing) {
|
||||
if(ar[x]->desc)
|
||||
fprintf(fd," : %s",ar[x]->desc,LF);
|
||||
if(ar[x]->size != -1)
|
||||
fprintf(fd," (%d bytes)",ar[x]->size);
|
||||
escape_url(t);
|
||||
|
||||
if(dir_opts & FANCY_INDEXING) {
|
||||
if(dir_opts & ICONS_ARE_LINKS)
|
||||
bytes_sent += fprintf(fd,"%s",anchor);
|
||||
if((ar[x]->icon) || default_icon[0]) {
|
||||
bytes_sent += fprintf(fd,"<IMG SRC=\"%s\" ALT=\"[%s]\">",
|
||||
ar[x]->icon ? ar[x]->icon : default_icon,
|
||||
ar[x]->alt ? ar[x]->alt : " ");
|
||||
}
|
||||
if(dir_opts & ICONS_ARE_LINKS) {
|
||||
fputs("</A>",fd);
|
||||
bytes_sent += 4;
|
||||
}
|
||||
bytes_sent += fprintf(fd," %s",anchor);
|
||||
bytes_sent += fprintf(fd,"%-27.27s",t2);
|
||||
if(ar[x]->lm != -1) {
|
||||
struct tm *ts = localtime(&ar[x]->lm);
|
||||
strftime(t,MAX_STRING_LEN,"%d-%h-%y %H:%M ",ts);
|
||||
fputs(t,fd);
|
||||
bytes_sent += strlen(t);
|
||||
}
|
||||
else {
|
||||
fputs(" ",fd);
|
||||
bytes_sent += 17;
|
||||
}
|
||||
send_size(ar[x]->size,fd);
|
||||
fputs(" ",fd);
|
||||
bytes_sent += 2;
|
||||
if(ar[x]->desc) {
|
||||
if(strlen(ar[x]->desc) > 23) {
|
||||
ar[x]->desc[23] = '>';
|
||||
ar[x]->desc[24] = '\0';
|
||||
}
|
||||
bytes_sent += fprintf(fd,"%s",ar[x]->desc);
|
||||
}
|
||||
}
|
||||
else
|
||||
bytes_sent += fprintf(fd,"<LI> %s %s",anchor,t2);
|
||||
fputc(LF,fd);
|
||||
++bytes_sent;
|
||||
}
|
||||
if(dir_opts & FANCY_INDEXING) {
|
||||
fputs("</PRE>",fd);
|
||||
bytes_sent += 6;
|
||||
}
|
||||
else {
|
||||
fputs("</UL>",fd);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int dsortf(struct ent **s1,struct ent **s2)
|
||||
{
|
||||
return(strcmp((*s1)->name,(*s2)->name));
|
||||
@ -256,26 +513,33 @@ void index_directory(char *name, FILE *fd)
|
||||
struct ent *head,*p,*q;
|
||||
struct ent **ar;
|
||||
char unmunged_name[MAX_STRING_LEN];
|
||||
char *tmp;
|
||||
|
||||
strcpy(unmunged_name,name);
|
||||
strcpy_dir(unmunged_name,name);
|
||||
unmunge_name(unmunged_name);
|
||||
|
||||
if(!(d=opendir(name)))
|
||||
die(FORBIDDEN,unmunged_name,fd);
|
||||
|
||||
strcpy(content_type,"text/html");
|
||||
status = 200;
|
||||
if(!assbackwards)
|
||||
send_http_header(fd);
|
||||
|
||||
if(header_only) return;
|
||||
|
||||
/* Spew HTML preamble */
|
||||
fprintf(fd,"<HEAD><TITLE>Index of %s</TITLE></HEAD>",unmunged_name);
|
||||
fputc(LF,fd);
|
||||
fprintf(fd,"<BODY><H1>Index of %s</H1>",unmunged_name);
|
||||
fputc(LF,fd);
|
||||
bytes_sent = 0;
|
||||
|
||||
fprintf(fd,fancy_indexing ? "<DL>%c" : "<UL>%c",LF);
|
||||
dir_opts = find_opts(name);
|
||||
|
||||
/* Spew HTML preamble */
|
||||
bytes_sent += fprintf(fd,"<HEAD><TITLE>Index of %s</TITLE></HEAD><BODY>",
|
||||
unmunged_name);
|
||||
fputc(LF,fd);
|
||||
++bytes_sent;
|
||||
|
||||
if((!(tmp = find_header(name))) || (!(insert_readme(name,tmp,0,fd))))
|
||||
bytes_sent += fprintf(fd,"<H1>Index of %s</H1>%c",unmunged_name,LF);
|
||||
|
||||
/*
|
||||
* Since we don't know how many dir. entries there are, put them into a
|
||||
@ -310,12 +574,21 @@ void index_directory(char *name, FILE *fd)
|
||||
while(q) {
|
||||
p=q->next;
|
||||
free(q->name);
|
||||
if(q->desc)
|
||||
free(q->desc);
|
||||
free(q);
|
||||
q=p;
|
||||
}
|
||||
closedir(d);
|
||||
fprintf(fd,fancy_indexing ? "</DL>" : "</UL>");
|
||||
if(fancy_indexing)
|
||||
insert_readme(name,fd);
|
||||
fprintf(fd,"</BODY>");
|
||||
if(dir_opts & FANCY_INDEXING)
|
||||
if(tmp = find_readme(name))
|
||||
insert_readme(name,tmp,1,fd);
|
||||
else {
|
||||
fputs("</UL>",fd);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
|
||||
fputs("</BODY>",fd);
|
||||
bytes_sent += 7;
|
||||
log_transaction();
|
||||
}
|
||||
|
121
src/http_get.c
121
src/http_get.c
@ -5,8 +5,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
|
||||
@ -16,34 +14,106 @@ int allow;
|
||||
char allow_options;
|
||||
|
||||
|
||||
void send_file(char *file, FILE *fd, char *args) {
|
||||
void send_file(char *file, FILE *fd, char *path_args, char *args) {
|
||||
FILE *f;
|
||||
struct stat finfo;
|
||||
|
||||
set_content_type(file);
|
||||
|
||||
if((allow_options & OPT_INCLUDES) &&
|
||||
(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) &&
|
||||
(!content_encoding[0]))
|
||||
{
|
||||
status = 200;
|
||||
bytes_sent = 0;
|
||||
send_parsed_file(file,fd,path_args,args,
|
||||
allow_options & OPT_INCNOEXEC);
|
||||
log_transaction();
|
||||
return;
|
||||
}
|
||||
if(!(f=fopen(file,"r"))) {
|
||||
log_reason("file permissions deny server access",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd); /* we've already established that it exists */
|
||||
}
|
||||
set_content_type(file);
|
||||
status = 200;
|
||||
bytes_sent = 0;
|
||||
if(!assbackwards) {
|
||||
fstat(fileno(f),&finfo);
|
||||
if(!((allow_options & OPT_INCLUDES) && is_content_type("text/html")))
|
||||
set_content_length(finfo.st_size);
|
||||
set_last_modified(finfo.st_mtime);
|
||||
set_content_length(finfo.st_size);
|
||||
set_last_modified(finfo.st_mtime,fd);
|
||||
send_http_header(fd);
|
||||
}
|
||||
num_includes=0;
|
||||
if(!header_only)
|
||||
send_fd(f,fd,args);
|
||||
send_fd(f,fd,NULL);
|
||||
log_transaction();
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void send_cgi(char *method, char *file, char *path_args, char *args,
|
||||
struct stat *finfo, int in, FILE *fd)
|
||||
{
|
||||
char **env;
|
||||
int m;
|
||||
|
||||
void send_node(char *file, char *args, FILE *fd)
|
||||
if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD")))
|
||||
m = M_GET;
|
||||
else if(!strcmp(method,"POST"))
|
||||
m = M_POST;
|
||||
else if(!strcmp(method,"PUT"))
|
||||
m = M_PUT;
|
||||
else if(!strcmp(method,"DELETE"))
|
||||
m = M_DELETE;
|
||||
|
||||
evaluate_access(file,finfo,m,&allow,&allow_options,fd);
|
||||
if((!allow) || (!(allow_options & OPT_EXECCGI))) {
|
||||
log_reason("client denied by server configuration",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
if(!(env = add_common_vars(in_headers_env,fd)))
|
||||
die(NO_MEMORY,"send_cgi",fd);
|
||||
bytes_sent = 0;
|
||||
if(cgi_stub(method,file,path_args,args,env,finfo,in,fd) == REDIRECT_URL)
|
||||
die(REDIRECT,location,fd);
|
||||
free_env(env);
|
||||
log_transaction();
|
||||
}
|
||||
|
||||
void send_node(char *file, char *args, int in, FILE *fd)
|
||||
{
|
||||
struct stat finfo;
|
||||
char pa[MAX_STRING_LEN];
|
||||
|
||||
pa[0] = '\0';
|
||||
if(stat(file,&finfo) == -1) {
|
||||
/* Look for script or include document */
|
||||
int n=count_dirs(file),i,l;
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
for(i=n;i;--i) {
|
||||
make_dirstr(file,i,t);
|
||||
probe_content_type(t);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
|
||||
if(stat(t,&finfo) == -1)
|
||||
continue;
|
||||
if(!(S_ISREG(finfo.st_mode)))
|
||||
break;
|
||||
l=strlen(t);
|
||||
strcpy(pa,&file[l]);
|
||||
file[l] = '\0';
|
||||
send_cgi("GET",file,pa,args,&finfo,in,fd);
|
||||
return;
|
||||
} else if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
|
||||
if(stat(t,&finfo) == -1)
|
||||
continue;
|
||||
l=strlen(t);
|
||||
strcpy(pa,&file[l]);
|
||||
file[l] = '\0';
|
||||
goto send_regular;
|
||||
}
|
||||
}
|
||||
if(errno==ENOENT) {
|
||||
log_reason("file does not exist",file);
|
||||
unmunge_name(file);
|
||||
@ -55,6 +125,13 @@ void send_node(char *file, char *args, FILE *fd)
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
}
|
||||
probe_content_type(file);
|
||||
if(S_ISREG(finfo.st_mode) && (!strcmp(content_type,CGI_MAGIC_TYPE))) {
|
||||
send_cgi("GET",file,"",args,&finfo,in,fd);
|
||||
return;
|
||||
}
|
||||
|
||||
send_regular: /* aaaaack */
|
||||
evaluate_access(file,&finfo,M_GET,&allow,&allow_options, fd);
|
||||
if(!allow) {
|
||||
log_reason("client denied by server configuration",file);
|
||||
@ -65,6 +142,13 @@ void send_node(char *file, char *args, FILE *fd)
|
||||
if(S_ISDIR(finfo.st_mode)) {
|
||||
char ifile[MAX_STRING_LEN];
|
||||
|
||||
if(file[strlen(file) - 1] != '/') {
|
||||
char url[MAX_STRING_LEN];
|
||||
strcpy_dir(ifile,file);
|
||||
unmunge_name(ifile);
|
||||
construct_url(url,ifile);
|
||||
die(REDIRECT,url,fd);
|
||||
}
|
||||
make_full_path(file,index_name,ifile);
|
||||
if(stat(ifile,&finfo) == -1) {
|
||||
if(allow_options & OPT_INDEXES)
|
||||
@ -76,19 +160,16 @@ void send_node(char *file, char *args, FILE *fd)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(file[strlen(file) - 1] != '/') {
|
||||
char url[MAX_STRING_LEN];
|
||||
strcpy_dir(ifile,file);
|
||||
unmunge_name(ifile);
|
||||
construct_url(url,ifile);
|
||||
die(REDIRECT,url,fd);
|
||||
}
|
||||
send_file(ifile,fd,args);
|
||||
probe_content_type(ifile);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE))
|
||||
send_cgi("GET",ifile,pa,args,&finfo,in,fd);
|
||||
else
|
||||
send_file(ifile,fd,pa,args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(S_ISREG(finfo.st_mode))
|
||||
send_file(file,fd,args);
|
||||
send_file(file,fd,pa,args);
|
||||
else {
|
||||
log_reason("improper file type",file);
|
||||
unmunge_name(file);
|
||||
@ -106,12 +187,12 @@ void process_get(int in, FILE *out, char *m, char *url, char *args) {
|
||||
s=translate_name(url,out);
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
send_node(url,args,out);
|
||||
send_node(url,args,in,out);
|
||||
return;
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,url,out);
|
||||
case SCRIPT_NCSA:
|
||||
exec_get_NCSA(url,args,out);
|
||||
exec_get_NCSA(url,args,in,out);
|
||||
return;
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script(m,url,args,in,out);
|
||||
|
619
src/http_include.c
Normal file
619
src/http_include.c
Normal file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
* http_include.c: Handles the server-parsed HTML documents
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
#define STARTING_SEQUENCE "<!--#"
|
||||
#define ENDING_SEQUENCE "-->"
|
||||
#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
|
||||
#define DEFAULT_TIME_FORMAT "%A, %d-%h-%y %T %Z"
|
||||
#define SIZEFMT_BYTES 0
|
||||
#define SIZEFMT_KMG 1
|
||||
|
||||
/* These are stored statically so that they can be reformatted quickly */
|
||||
static time_t date,lm;
|
||||
|
||||
/* ------------------------ Environment function -------------------------- */
|
||||
|
||||
#define NUM_INCLUDE_VARS 5
|
||||
|
||||
char **add_include_vars(char **env,char *file, char *path_args, char *args,
|
||||
char *timefmt,FILE *out)
|
||||
{
|
||||
int x;
|
||||
struct stat finfo;
|
||||
char ufile[HUGE_STRING_LEN];
|
||||
char *t;
|
||||
|
||||
if(!(env = new_env(env,NUM_INCLUDE_VARS,&x)))
|
||||
die(NO_MEMORY,"add_include_vars",out);
|
||||
date = time(NULL);
|
||||
env[x++] = make_env_str("DATE_LOCAL",ht_time(date,timefmt,0),out);
|
||||
env[x++] = make_env_str("DATE_GMT",ht_time(date,timefmt,1),out);
|
||||
|
||||
if(stat(file,&finfo) != -1) {
|
||||
lm = finfo.st_mtime;
|
||||
env[x++] = make_env_str("LAST_MODIFIED",ht_time(lm,timefmt,1),out);
|
||||
}
|
||||
strcpy(ufile,file);
|
||||
unmunge_name(ufile);
|
||||
env[x++] = make_env_str("DOCUMENT_URI",ufile,out);
|
||||
if(t = strrchr(ufile,'/'))
|
||||
++t;
|
||||
else
|
||||
t = ufile;
|
||||
env[x++] = make_env_str("DOCUMENT_NAME",t,out);
|
||||
env[x] = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
#define GET_CHAR(f,c,r) \
|
||||
{ \
|
||||
int i = getc(f); \
|
||||
if(feof(f) || ferror(f) || (i == -1)) { \
|
||||
fclose(f); \
|
||||
return r; \
|
||||
} \
|
||||
c = (char)i; \
|
||||
}
|
||||
|
||||
/* --------------------------- Parser functions --------------------------- */
|
||||
|
||||
int find_string(FILE *in,char *str, FILE *out) {
|
||||
int x,l=strlen(str),p;
|
||||
char c;
|
||||
|
||||
p=0;
|
||||
while(1) {
|
||||
GET_CHAR(in,c,1);
|
||||
if(c == str[p]) {
|
||||
if((++p) == l)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if(out) {
|
||||
if(p) {
|
||||
for(x=0;x<p;x++) {
|
||||
putc(str[x],out);
|
||||
++bytes_sent;
|
||||
}
|
||||
}
|
||||
putc(c,out);
|
||||
++bytes_sent;
|
||||
}
|
||||
p=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *get_tag(FILE *in, char *tag) {
|
||||
char *t = tag, *tag_val, c;
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
while(1) {
|
||||
GET_CHAR(in,c,NULL);
|
||||
if(!isspace(c)) break;
|
||||
}
|
||||
/* problem: this drops tags starting with - or -- (tough s***) */
|
||||
if(c == '-') {
|
||||
GET_CHAR(in,c,NULL);
|
||||
if(c == '-') {
|
||||
GET_CHAR(in,c,NULL);
|
||||
if(c == '>') {
|
||||
strcpy(tag,"done");
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* this parser is very rigid, needs quotes around value and no spaces */
|
||||
while(1) {
|
||||
if(++n == MAX_STRING_LEN) {
|
||||
t[MAX_STRING_LEN - 1] = '\0';
|
||||
return NULL;
|
||||
}
|
||||
if((*t = c) == '\\') {
|
||||
GET_CHAR(in,c,NULL);
|
||||
*t = c;
|
||||
} else if(*t == '=') {
|
||||
*t++ = '\0';
|
||||
tag_val = t;
|
||||
GET_CHAR(in,c,NULL);
|
||||
if(c == '\"') {
|
||||
while(1) {
|
||||
GET_CHAR(in,c,NULL);
|
||||
if(++n == MAX_STRING_LEN) {
|
||||
t[MAX_STRING_LEN - 1] = '\0';
|
||||
return NULL;
|
||||
}
|
||||
if((*t = c) == '\\') {
|
||||
GET_CHAR(in,c,NULL);
|
||||
*t = c;
|
||||
} else if(*t == '\"') {
|
||||
*t = '\0';
|
||||
return tag_val;
|
||||
}
|
||||
++t;
|
||||
}
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
++t;
|
||||
GET_CHAR(in,c,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int get_directive(FILE *in,char *d) {
|
||||
char c;
|
||||
|
||||
/* skip initial whitespace */
|
||||
while(1) {
|
||||
GET_CHAR(in,c,1);
|
||||
if(!isspace(c))
|
||||
break;
|
||||
}
|
||||
/* now get directive */
|
||||
while(1) {
|
||||
*d++ = c;
|
||||
GET_CHAR(in,c,1);
|
||||
if(isspace(c))
|
||||
break;
|
||||
}
|
||||
*d = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------- Action handlers ---------------------------- */
|
||||
|
||||
int send_included_file(char *file, FILE *out, char *fn) {
|
||||
FILE *f;
|
||||
struct stat finfo;
|
||||
int allow;char op,i;
|
||||
|
||||
if(stat(file,&finfo) == -1)
|
||||
return -1;
|
||||
evaluate_access(file,&finfo,M_GET,&allow,&op,out);
|
||||
if(!allow)
|
||||
return -1;
|
||||
set_content_type(file);
|
||||
if((op & OPT_INCLUDES) && (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
|
||||
send_parsed_file(file,out,"","",op & OPT_INCNOEXEC);
|
||||
chdir_file(fn); /* grumble */
|
||||
}
|
||||
else if(!strcmp(content_type,CGI_MAGIC_TYPE))
|
||||
return -1;
|
||||
else {
|
||||
if(!(f=fopen(file,"r")))
|
||||
return -1;
|
||||
send_fd(f,out,NULL);
|
||||
fclose(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_include(FILE *in, FILE *out, char *fn, char *error) {
|
||||
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
if(!strcmp(tag,"file")) {
|
||||
char dir[MAX_STRING_LEN],to_send[MAX_STRING_LEN];
|
||||
|
||||
getparents(tag_val); /* get rid of any nasties */
|
||||
getwd(dir);
|
||||
make_full_path(dir,tag_val,to_send);
|
||||
if(send_included_file(to_send,out,fn)) {
|
||||
sprintf(errstr,"unable to include %s in parsed file %s",
|
||||
tag_val, fn);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
else if(!strcmp(tag,"virtual")) {
|
||||
if(translate_name(tag_val,out) != STD_DOCUMENT) {
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
log_error_noclose(errstr);
|
||||
}
|
||||
else if(send_included_file(tag_val,out,fn)) {
|
||||
sprintf(errstr,"unable to include %s in parsed file %s",
|
||||
tag_val, fn);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else {
|
||||
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,fn);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int handle_echo(FILE *in, FILE *out, char *file, char *error, char **env) {
|
||||
char tag[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
if(!strcmp(tag,"var")) {
|
||||
int x,i;
|
||||
|
||||
for(x=0;env[x] != NULL; x++) {
|
||||
i = ind(env[x],'=');
|
||||
if(!strncmp(env[x],tag_val,i)) {
|
||||
bytes_sent += fprintf(out,"%s",&env[x][i+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!env[x]) bytes_sent += fprintf(out,"(none)");
|
||||
} else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int include_cgi(char *s, char *pargs, char *args, char **env, FILE *out)
|
||||
{
|
||||
char *argp,op,d[HUGE_STRING_LEN];
|
||||
int allow,check_cgiopt;
|
||||
struct stat finfo;
|
||||
|
||||
getparents(s);
|
||||
if(s[0] == '/') {
|
||||
strcpy(d,s);
|
||||
if(translate_name(d,out) != SCRIPT_CGI)
|
||||
return -1;
|
||||
check_cgiopt=0;
|
||||
} else {
|
||||
char dir[MAX_STRING_LEN];
|
||||
getwd(dir);
|
||||
make_full_path(dir,s,d);
|
||||
check_cgiopt=1;
|
||||
}
|
||||
/* No hardwired path info or query allowed */
|
||||
if(stat(d,&finfo) == -1)
|
||||
return -1;
|
||||
|
||||
evaluate_access(d,&finfo,M_GET,&allow,&op,out);
|
||||
if((!allow) || (check_cgiopt && (!(op & OPT_EXECCGI))))
|
||||
return -1;
|
||||
|
||||
if(cgi_stub("GET",d,pargs,args,env,&finfo,-1,out) == REDIRECT_URL)
|
||||
bytes_sent += fprintf(out,"<A HREF=\"%s\">%s</A>",location,location);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipid;
|
||||
void kill_include_child() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"killing command process %d",ipid);
|
||||
log_error_noclose(errstr);
|
||||
kill(ipid,SIGKILL);
|
||||
waitpid(ipid,NULL,0);
|
||||
}
|
||||
|
||||
int include_cmd(char *s, char *pargs, char *args, char **env, FILE *out) {
|
||||
int p[2],x;
|
||||
FILE *f;
|
||||
|
||||
if(pipe(p) == -1)
|
||||
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
|
||||
if((ipid = fork()) == -1)
|
||||
die(SERVER_ERROR,"httpd: could not fork new process",out);
|
||||
if(!ipid) {
|
||||
char *argv0;
|
||||
|
||||
if(pargs[0] || args[0]) {
|
||||
if(!(env = new_env(env,4,&x)))
|
||||
return -1;
|
||||
if(pargs[0]) {
|
||||
char p2[HUGE_STRING_LEN];
|
||||
|
||||
escape_shell_cmd(pargs);
|
||||
env[x++] = make_env_str("PATH_INFO",pargs,out);
|
||||
strcpy(p2,pargs);
|
||||
translate_name(p2,out);
|
||||
env[x++] = make_env_str("PATH_TRANSLATED",p2,out);
|
||||
}
|
||||
if(args[0]) {
|
||||
env[x++] = make_env_str("QUERY_STRING",args,out);
|
||||
unescape_url(args);
|
||||
escape_shell_cmd(args);
|
||||
env[x++] = make_env_str("QUERY_STRING_UNESCAPED",args,out);
|
||||
}
|
||||
env[x] = NULL;
|
||||
}
|
||||
|
||||
close(p[0]);
|
||||
if(p[1] != STDOUT_FILENO) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
error_log2stderr();
|
||||
if(!(argv0 = strrchr(SHELL_PATH,'/')))
|
||||
argv0=SHELL_PATH;
|
||||
if(execle(SHELL_PATH,argv0,"-c",s,(char *)0,env) == -1) {
|
||||
fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
|
||||
SHELL_PATH,errno);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
close(p[1]);
|
||||
if(!(f=fdopen(p[0],"r"))) {
|
||||
waitpid(ipid,NULL,0);
|
||||
return -1;
|
||||
}
|
||||
send_fd(f,out,kill_include_child);
|
||||
fclose(f);
|
||||
waitpid(ipid,NULL,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int handle_exec(FILE *in, FILE *out, char *file, char *path_args, char *args,
|
||||
char *error, char **env)
|
||||
{
|
||||
char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
if(!strcmp(tag,"cmd")) {
|
||||
if(include_cmd(tag_val,path_args,args,env,out) == -1) {
|
||||
sprintf(errstr,"invalid command exec %s in %s",tag_val,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
/* just in case some stooge changed directories */
|
||||
chdir_file(file);
|
||||
}
|
||||
else if(!strcmp(tag,"cgi")) {
|
||||
if(include_cgi(tag_val,path_args,args,env,out) == -1) {
|
||||
sprintf(errstr,"invalid CGI ref %s in %s",tag_val,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
/* grumble groan */
|
||||
chdir_file(file);
|
||||
}
|
||||
else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int handle_config(FILE *in, FILE *out, char *file, char *error, char *tf,
|
||||
int *sizefmt, char **env) {
|
||||
char tag[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
if(!strcmp(tag,"errmsg"))
|
||||
strcpy(error,tag_val);
|
||||
else if(!strcmp(tag,"timefmt")) {
|
||||
strcpy(tf,tag_val);
|
||||
/* Replace DATE* and LAST_MODIFIED (they should be first) */
|
||||
free(env[0]);
|
||||
env[0] = make_env_str("DATE_LOCAL",ht_time(date,tf,0),out);
|
||||
free(env[1]);
|
||||
env[1] = make_env_str("DATE_GMT",ht_time(date,tf,1),out);
|
||||
if(!strncmp(env[2],"LAST_MODIFIED",13)) {
|
||||
free(env[2]);
|
||||
env[2] = make_env_str("LAST_MODIFIED",ht_time(lm,tf,1),out);
|
||||
}
|
||||
}
|
||||
else if(!strcmp(tag,"sizefmt")) {
|
||||
if(!strcmp(tag_val,"bytes"))
|
||||
*sizefmt = SIZEFMT_BYTES;
|
||||
else if(!strcmp(tag_val,"abbrev"))
|
||||
*sizefmt = SIZEFMT_KMG;
|
||||
}
|
||||
else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"unknown parameter %s to tag config in %s",
|
||||
tag,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int find_file(FILE *out, char *file, char *directive, char *tag,
|
||||
char *tag_val, struct stat *finfo, char *error)
|
||||
{
|
||||
char errstr[MAX_STRING_LEN], dir[MAX_STRING_LEN], to_send[MAX_STRING_LEN];
|
||||
|
||||
if(!strcmp(tag,"file")) {
|
||||
getparents(tag_val); /* get rid of any nasties */
|
||||
getwd(dir);
|
||||
make_full_path(dir,tag_val,to_send);
|
||||
if(stat(to_send,finfo) == -1) {
|
||||
sprintf(errstr,
|
||||
"unable to get information about %s in parsed file %s",
|
||||
to_send,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if(!strcmp(tag,"virtual")) {
|
||||
if(translate_name(tag_val,out) != STD_DOCUMENT) {
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
log_error_noclose(errstr);
|
||||
}
|
||||
else if(stat(tag_val,finfo) == -1) {
|
||||
sprintf(errstr,
|
||||
"unable to get information about %s in parsed file %s",
|
||||
to_send,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
sprintf(errstr,"unknown parameter %s to tag %s in %s",
|
||||
tag,directive,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(out,"%s",error);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int handle_fsize(FILE *in, FILE *out, char *file, char *error, int sizefmt,
|
||||
char **env)
|
||||
{
|
||||
char tag[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
struct stat finfo;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else if(!find_file(out,file,"fsize",tag,tag_val,&finfo,error)) {
|
||||
if(sizefmt == SIZEFMT_KMG) {
|
||||
send_size(finfo.st_size,out);
|
||||
bytes_sent += 5;
|
||||
}
|
||||
else {
|
||||
int l,x;
|
||||
sprintf(tag,"%ld",finfo.st_size);
|
||||
l = strlen(tag); /* grrr */
|
||||
for(x=0;x<l;x++) {
|
||||
if(x && (!((l-x) % 3))) {
|
||||
fputc(',',out);
|
||||
++bytes_sent;
|
||||
}
|
||||
fputc(tag[x],out);
|
||||
++bytes_sent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int handle_flastmod(FILE *in, FILE *out, char *file, char *error, char *tf,
|
||||
char **env)
|
||||
{
|
||||
char tag[MAX_STRING_LEN];
|
||||
char *tag_val;
|
||||
struct stat finfo;
|
||||
|
||||
while(1) {
|
||||
if(!(tag_val = get_tag(in,tag)))
|
||||
return 1;
|
||||
else if(!strcmp(tag,"done"))
|
||||
return 0;
|
||||
else if(!find_file(out,file,"flastmod",tag,tag_val,&finfo,error))
|
||||
bytes_sent += fprintf(out,"%s",ht_time(finfo.st_mtime,tf,0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------- The main function --------------------------- */
|
||||
|
||||
void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
|
||||
int noexec)
|
||||
{
|
||||
char directive[MAX_STRING_LEN], error[MAX_STRING_LEN], c, **env;
|
||||
char timefmt[MAX_STRING_LEN], errstr[MAX_STRING_LEN];
|
||||
int ret, sizefmt;
|
||||
FILE *f;
|
||||
|
||||
if(!(f=fopen(file,"r"))) {
|
||||
log_reason("file permissions deny server access",file);
|
||||
unmunge_name(file);
|
||||
die(FORBIDDEN,file,fd);
|
||||
}
|
||||
strcpy(content_type,"text/html");
|
||||
if(!assbackwards)
|
||||
send_http_header(fd);
|
||||
if(header_only)
|
||||
return;
|
||||
|
||||
/* Make sure no children inherit our buffers */
|
||||
fflush(fd);
|
||||
assbackwards = 1; /* make sure no headers get inserted anymore */
|
||||
alarm(timeout);
|
||||
|
||||
strcpy(error,DEFAULT_ERROR_MSG);
|
||||
strcpy(timefmt,DEFAULT_TIME_FORMAT);
|
||||
sizefmt = SIZEFMT_KMG;
|
||||
chdir_file(file);
|
||||
env = add_include_vars(in_headers_env,file,path_args,args,timefmt,fd);
|
||||
env = add_common_vars(env,fd);
|
||||
|
||||
while(1) {
|
||||
if(!find_string(f,STARTING_SEQUENCE,fd)) {
|
||||
if(get_directive(f,directive))
|
||||
goto bye;
|
||||
if(!strcmp(directive,"exec")) {
|
||||
if(noexec) {
|
||||
sprintf(errstr,"httpd: exec used but not allowed in %s",
|
||||
file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(fd,"%s",error);
|
||||
ret = find_string(f,ENDING_SEQUENCE,NULL);
|
||||
} else
|
||||
ret=handle_exec(f,fd,file,path_args,args,error,env);
|
||||
}
|
||||
else if(!strcmp(directive,"config"))
|
||||
ret=handle_config(f,fd,file,error,timefmt,&sizefmt,env);
|
||||
else if(!strcmp(directive,"include"))
|
||||
ret=handle_include(f,fd,file,error);
|
||||
else if(!strcmp(directive,"echo"))
|
||||
ret=handle_echo(f,fd,file,error,env);
|
||||
else if(!strcmp(directive,"fsize"))
|
||||
ret=handle_fsize(f,fd,file,error,sizefmt,env);
|
||||
else if(!strcmp(directive,"flastmod"))
|
||||
ret=handle_flastmod(f,fd,file,error,timefmt,env);
|
||||
else {
|
||||
sprintf(errstr,"httpd: unknown directive %s in parsed doc %s",
|
||||
directive,file);
|
||||
log_error_noclose(errstr);
|
||||
bytes_sent += fprintf(fd,"%s",error);
|
||||
ret=find_string(f,ENDING_SEQUENCE,NULL);
|
||||
}
|
||||
if(ret) {
|
||||
sprintf(errstr,"httpd: premature EOF in parsed file %s",file);
|
||||
log_error_noclose(errstr);
|
||||
goto bye;
|
||||
}
|
||||
} else
|
||||
goto bye;
|
||||
}
|
||||
bye:
|
||||
free_env(env);
|
||||
}
|
107
src/http_log.c
107
src/http_log.c
@ -8,7 +8,7 @@
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
static FILE *error_log;
|
||||
FILE *error_log;
|
||||
static FILE *xfer_log;
|
||||
|
||||
void open_logs() {
|
||||
@ -18,9 +18,6 @@ void open_logs() {
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
/* Make sure nasty scripts or includes send errors here */
|
||||
if(fileno(error_log) != STDERR_FILENO)
|
||||
dup2(fileno(error_log),STDERR_FILENO);
|
||||
if(!(xfer_log = fopen(xfer_fname,"a"))) {
|
||||
fprintf(stderr,"httpd: could not open transfer log file %s.\n",
|
||||
xfer_fname);
|
||||
@ -32,7 +29,11 @@ void open_logs() {
|
||||
void close_logs() {
|
||||
fclose(xfer_log);
|
||||
fclose(error_log);
|
||||
fclose(stderr);
|
||||
}
|
||||
|
||||
void error_log2stderr() {
|
||||
if(fileno(error_log) != STDERR_FILENO)
|
||||
dup2(fileno(error_log),STDERR_FILENO);
|
||||
}
|
||||
|
||||
void log_pid() {
|
||||
@ -46,13 +47,67 @@ void log_pid() {
|
||||
fclose(pid_file);
|
||||
}
|
||||
|
||||
void log_transaction(char *cmd_line) {
|
||||
static char the_request[HUGE_STRING_LEN];
|
||||
int status;
|
||||
int bytes_sent;
|
||||
|
||||
void record_request(char *cmd_line) {
|
||||
status = -1;
|
||||
bytes_sent = -1;
|
||||
|
||||
strcpy(the_request,cmd_line);
|
||||
#if 0
|
||||
if(!do_rfc931)
|
||||
fprintf(xfer_log, "%s [%s] %s\n", remote_name, get_time(), cmd_line);
|
||||
else
|
||||
fprintf(xfer_log, "%s@%s [%s] %s\n", remote_logname, remote_name,
|
||||
get_time(), cmd_line);
|
||||
fclose(xfer_log); /* we should be done with it... */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NEXT MUST DIE. */
|
||||
static char *mon[] = {
|
||||
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
||||
};
|
||||
|
||||
void log_transaction() {
|
||||
char str[HUGE_STRING_LEN];
|
||||
long timz;
|
||||
struct tm *t;
|
||||
char tstr[MAX_STRING_LEN],sign;
|
||||
|
||||
t = get_gmtoff(&timz);
|
||||
sign = (timz < 0 ? '-' : '+');
|
||||
if(timz < 0)
|
||||
timz = -timz;
|
||||
|
||||
sprintf(tstr,"%2d/%s/%4d:%2d:%2d:%2d",
|
||||
t->tm_mday,mon[t->tm_mon],1900 + t->tm_year,
|
||||
t->tm_hour,t->tm_min,t->tm_sec);
|
||||
|
||||
strftime(tstr,MAX_STRING_LEN,"%d/%h/%Y:%H:%M:%S",t);
|
||||
|
||||
sprintf(str,"%s %s %s [%s %c%02d%02d] \"%s\" ",
|
||||
remote_name,
|
||||
(do_rfc931 ? remote_logname : "-"),
|
||||
(user[0] ? user : "-"),
|
||||
tstr,
|
||||
sign,
|
||||
timz/3600,
|
||||
timz%3600,
|
||||
the_request);
|
||||
if(status != -1)
|
||||
sprintf(str,"%s%d ",str,status);
|
||||
else
|
||||
strcat(str,"- ");
|
||||
|
||||
if(bytes_sent != -1)
|
||||
sprintf(str,"%s%d",str,bytes_sent);
|
||||
else
|
||||
strcat(str,"- ");
|
||||
fprintf(xfer_log,"%s\n",str);
|
||||
fclose(xfer_log);
|
||||
}
|
||||
|
||||
void log_error(char *err) {
|
||||
@ -60,6 +115,11 @@ void log_error(char *err) {
|
||||
fclose(error_log);
|
||||
}
|
||||
|
||||
void log_error_noclose(char *err) {
|
||||
fprintf(error_log, "[%s] %s\n",get_time(),err);
|
||||
fflush(error_log);
|
||||
}
|
||||
|
||||
void log_reason(char *reason, char *file) {
|
||||
char t[MAX_STRING_LEN];
|
||||
|
||||
@ -76,8 +136,7 @@ void begin_http_header(FILE *fd, char *msg) {
|
||||
void error_head(FILE *fd, char *err) {
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,err);
|
||||
fprintf(fd,"Content-type: text/html%c",LF);
|
||||
fprintf(fd,"%c",LF);
|
||||
fprintf(fd,"Content-type: text/html%c%c",LF,LF);
|
||||
}
|
||||
if(!header_only) {
|
||||
fprintf(fd,"<HEAD><TITLE>%s</TITLE></HEAD>%c",err,LF);
|
||||
@ -95,6 +154,7 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
|
||||
switch(type) {
|
||||
case REDIRECT:
|
||||
status = 302;
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,"302 Found");
|
||||
fprintf(fd,"Location: %s%c",err_string,LF);
|
||||
@ -106,9 +166,17 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
fprintf(fd,"This document has moved <A HREF=\"%s\">here</A>.<P>%c",
|
||||
err_string,LF);
|
||||
break;
|
||||
case USE_LOCAL_COPY:
|
||||
status = USE_LOCAL_COPY;
|
||||
begin_http_header(fd,"304 Not modified");
|
||||
fputc(LF,fd);
|
||||
header_only = 1;
|
||||
break;
|
||||
case AUTH_REQUIRED:
|
||||
status = 401;
|
||||
if(!assbackwards) {
|
||||
begin_http_header(fd,"401 Unauthorized");
|
||||
fprintf(fd,"Content-type: text/html%c",LF);
|
||||
fprintf(fd,"WWW-Authenticate: %s%c%c",err_string,LF,LF);
|
||||
}
|
||||
if(header_only) break;
|
||||
@ -117,6 +185,7 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
fprintf(fd,"authentication failed.%c",LF);
|
||||
break;
|
||||
case BAD_REQUEST:
|
||||
status = 400;
|
||||
error_head(fd,"400 Bad Request");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"Your client sent a query that this server could not%c",LF);
|
||||
@ -124,6 +193,7 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
fprintf(fd,"Reason: %s<P>%c",err_string,LF);
|
||||
break;
|
||||
case FORBIDDEN:
|
||||
status = 403;
|
||||
error_head(fd,"403 Forbidden");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"Your client does not have permission to get URL %s ",
|
||||
@ -131,12 +201,14 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
fprintf(fd,"from this server.<P>%c",LF);
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
status = 404;
|
||||
error_head(fd,"404 Not Found");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"The requested URL %s was not found on this server.<P>%c",
|
||||
err_string,LF);
|
||||
break;
|
||||
case SERVER_ERROR:
|
||||
status = 500;
|
||||
error_head(fd,"500 Server Error");
|
||||
log_error(err_string);
|
||||
if(header_only)
|
||||
@ -150,16 +222,8 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
fprintf(fd,"anything you might have done that may have caused%c",LF);
|
||||
fprintf(fd,"the error.<P>%c",LF);
|
||||
break;
|
||||
case INCLUDE_ERROR:
|
||||
/* error_head(fd,"500 Server Error"); */
|
||||
log_error(err_string);
|
||||
if(header_only) break;
|
||||
fprintf(fd,"[we're sorry, the following error has occurred: %s]%c",
|
||||
err_string,LF);
|
||||
fflush(fd);
|
||||
htexit(1,fd);
|
||||
break;
|
||||
case NOT_IMPLEMENTED:
|
||||
status = 501;
|
||||
error_head(fd,"501 Not Implemented");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"We are sorry to be unable to perform the method %s",
|
||||
@ -171,9 +235,18 @@ void die(int type, char *err_string, FILE *fd) {
|
||||
SERVER_VERSION,LF);
|
||||
fprintf(fd,"to <ADDRESS>%s</ADDRESS><P>%c",SERVER_SUPPORT,LF);
|
||||
break;
|
||||
case NO_MEMORY:
|
||||
log_error("httpd: memory exhausted");
|
||||
status = 500;
|
||||
error_head(fd,"500 Server Error");
|
||||
if(header_only) break;
|
||||
fprintf(fd,"The server has temporarily run out of resources for%c",LF);
|
||||
fprintf(fd,"your request. Please try again at a later time.<P>%c",LF);
|
||||
break;
|
||||
}
|
||||
if(!header_only)
|
||||
fprintf(fd,"</BODY>%c",LF);
|
||||
fflush(fd);
|
||||
log_transaction();
|
||||
htexit(1,fd);
|
||||
}
|
||||
|
196
src/http_mime.c
196
src/http_mime.c
@ -14,7 +14,11 @@ struct mime_ext {
|
||||
struct mime_ext *next;
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define hash(i) (isalpha(i) ? (tolower(i)) - 'a' : 26)
|
||||
#else
|
||||
#define hash(i) ((i) % 27)
|
||||
#endif
|
||||
|
||||
/* Hash table */
|
||||
struct mime_ext *types[27];
|
||||
@ -23,14 +27,19 @@ struct mime_ext *encoding_types;
|
||||
|
||||
int content_length;
|
||||
char content_type[MAX_STRING_LEN];
|
||||
char content_encoding[MAX_STRING_LEN];
|
||||
|
||||
char location[MAX_STRING_LEN];
|
||||
static char last_modified[MAX_STRING_LEN];
|
||||
static char content_encoding[MAX_STRING_LEN];
|
||||
char http_accept[HUGE_STRING_LEN];
|
||||
|
||||
char auth_line[MAX_STRING_LEN];
|
||||
|
||||
char *out_headers;
|
||||
char **in_headers_env;
|
||||
char *status_line;
|
||||
char ims[MAX_STRING_LEN]; /* If-modified-since */
|
||||
|
||||
|
||||
void hash_insert(struct mime_ext *me) {
|
||||
register int i = hash(me->ext[0]);
|
||||
register struct mime_ext *p, *q;
|
||||
@ -151,7 +160,7 @@ int is_content_type(char *type) {
|
||||
return(!strcmp(content_type,type));
|
||||
}
|
||||
|
||||
void set_content_type(char *file) {
|
||||
void find_ct(char *file, int store_encoding) {
|
||||
int i,l,l2;
|
||||
struct mime_ext *p;
|
||||
char fn[MAX_STRING_LEN];
|
||||
@ -165,10 +174,13 @@ void set_content_type(char *file) {
|
||||
while(p) {
|
||||
if(!strcmp(p->ext,&fn[i])) {
|
||||
fn[i-1] = '\0';
|
||||
if(content_encoding[0])
|
||||
sprintf(content_encoding,"%s, %s",content_encoding,p->ct);
|
||||
else
|
||||
strcpy(content_encoding,p->ct);
|
||||
if(store_encoding) {
|
||||
if(content_encoding[0])
|
||||
sprintf(content_encoding,"%s, %s",content_encoding,
|
||||
p->ct);
|
||||
else
|
||||
strcpy(content_encoding,p->ct);
|
||||
}
|
||||
if((i=rind(fn,'.')) < 0)
|
||||
break;
|
||||
++i;
|
||||
@ -208,20 +220,57 @@ void set_content_type(char *file) {
|
||||
strcpy(content_type,default_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void probe_content_type(char *file) {
|
||||
find_ct(file,0);
|
||||
}
|
||||
|
||||
void set_content_type(char *file) {
|
||||
find_ct(file,1);
|
||||
}
|
||||
|
||||
int scan_script_header(FILE *f, FILE *fd) {
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
char *l;
|
||||
int p;
|
||||
|
||||
while(1) {
|
||||
if(getline(l,MAX_STRING_LEN,fileno(f),timeout))
|
||||
if(getline(w,MAX_STRING_LEN-1,fileno(f),timeout))
|
||||
die(SERVER_ERROR,"httpd: malformed header from script",fd);
|
||||
|
||||
if(l[0] == '\0') return is_url(location);
|
||||
getword(w,l,':');
|
||||
if(w[0] == '\0') return is_url(location);
|
||||
if(!(l = strchr(w,':')))
|
||||
l = w;
|
||||
*l++ = '\0';
|
||||
if(!strcasecmp(w,"Content-type"))
|
||||
sscanf(l,"%s",content_type);
|
||||
else if(!strcasecmp(w,"Location"))
|
||||
sscanf(l,"%s",location);
|
||||
else if(!strcasecmp(w,"Status")) {
|
||||
for(p=0;isspace(l[p]);p++);
|
||||
sscanf(&l[p],"%d",&status);
|
||||
if(!(status_line = strdup(&l[p])))
|
||||
die(NO_MEMORY,"scan_script_header",fd);
|
||||
}
|
||||
else {
|
||||
*(--l) = ':';
|
||||
for(p=0;w[p];p++);
|
||||
w[p] = LF;
|
||||
w[++p] = '\0';
|
||||
if(!out_headers) {
|
||||
if(!(out_headers = strdup(w)))
|
||||
die(NO_MEMORY,"scan_script_header",fd);
|
||||
}
|
||||
else {
|
||||
int loh = strlen(out_headers);
|
||||
out_headers = (char *) realloc(out_headers,
|
||||
(loh+strlen(w)+1)*sizeof(char));
|
||||
if(!out_headers)
|
||||
die(NO_MEMORY,"scan_script_header",fd);
|
||||
strcpy(&out_headers[loh],w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,41 +306,109 @@ void set_content_length(int l) {
|
||||
content_length = l;
|
||||
}
|
||||
|
||||
void set_last_modified(time_t t) {
|
||||
void set_last_modified(time_t t, FILE *out) {
|
||||
strcpy(last_modified,gm_timestr_822(t));
|
||||
|
||||
if(!ims[0])
|
||||
return;
|
||||
|
||||
if(later_than(last_modified, ims))
|
||||
die(USE_LOCAL_COPY,NULL,out);
|
||||
}
|
||||
|
||||
void get_mime_headers(int fd) {
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
|
||||
void init_header_vars() {
|
||||
content_type[0] = '\0';
|
||||
last_modified[0] = '\0';
|
||||
content_length = -1;
|
||||
auth_line[0] = '\0';
|
||||
content_encoding[0] = '\0';
|
||||
http_accept[0] = '\0';
|
||||
location[0] = '\0';
|
||||
ims[0] = '\0';
|
||||
status_line = NULL;
|
||||
out_headers = NULL;
|
||||
in_headers_env = NULL;
|
||||
}
|
||||
|
||||
while(!(getline(l,MAX_STRING_LEN,fd,timeout))) {
|
||||
getword(w,l,':');
|
||||
if(!strcasecmp(w,"Content-type"))
|
||||
sscanf(l,"%s",content_type);
|
||||
else if(!strcasecmp(w,"Authorization"))
|
||||
strcpy(auth_line,l);
|
||||
else if(!strcasecmp(w,"Content-length"))
|
||||
sscanf(l,"%d",&content_length);
|
||||
else if(!strcasecmp(w,"Accept")) {
|
||||
if(http_accept[0])
|
||||
sprintf(http_accept,"%s, %s%c",http_accept,l,'\0');
|
||||
else
|
||||
strcpy(http_accept,l);
|
||||
int merge_header(char *h, char *v, FILE *out) {
|
||||
register int x,l,lt;
|
||||
char **t;
|
||||
|
||||
for(l=0;h[l];++l);
|
||||
h[l] = '=';
|
||||
h[++l] = '\0';
|
||||
|
||||
for(t=in_headers_env;*t;++t) {
|
||||
if(!strncmp(*t,h,l)) {
|
||||
lt = strlen(*t);
|
||||
if(!(*t = (char *) realloc(*t,(lt+strlen(v)+3)*sizeof(char))))
|
||||
die(NO_MEMORY,"merge_header",out);
|
||||
(*t)[lt++] = ',';
|
||||
(*t)[lt++] = ' ';
|
||||
strcpy(&((*t)[lt]),v);
|
||||
return 1;
|
||||
}
|
||||
else if(!l[0])
|
||||
}
|
||||
h[l-1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_mime_headers(int fd, FILE *out) {
|
||||
char w[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
int num_inh, num_processed;
|
||||
char *t;
|
||||
|
||||
num_inh = 0;
|
||||
num_processed = 0;
|
||||
|
||||
while(!(getline(w,MAX_STRING_LEN-1,fd,timeout))) {
|
||||
if(!w[0])
|
||||
return;
|
||||
if((++num_processed) > MAX_HEADERS)
|
||||
die(BAD_REQUEST,"too many header lines",out);
|
||||
if(!(t = strchr(w,':')))
|
||||
continue;
|
||||
*t++ = '\0';
|
||||
while(isspace(*t)) ++t;
|
||||
strcpy(l,t);
|
||||
|
||||
if(!strcasecmp(w,"Content-type")) {
|
||||
strcpy(content_type,l);
|
||||
continue;
|
||||
}
|
||||
if(!strcasecmp(w,"Authorization")) {
|
||||
strcpy(auth_line,l);
|
||||
continue;
|
||||
}
|
||||
if(!strcasecmp(w,"Content-length")) {
|
||||
sscanf(l,"%d",&content_length);
|
||||
continue;
|
||||
}
|
||||
if(!strcasecmp(w,"If-modified-since"))
|
||||
strcpy(ims,l);
|
||||
|
||||
http2cgi(w);
|
||||
if(in_headers_env) {
|
||||
if(!merge_header(w,l,out)) {
|
||||
in_headers_env =
|
||||
(char **) realloc(in_headers_env,
|
||||
(num_inh+2)*sizeof(char *));
|
||||
if(!in_headers_env)
|
||||
die(NO_MEMORY,"get_mime_headers",out);
|
||||
in_headers_env[num_inh++] = make_env_str(w,l,out);
|
||||
in_headers_env[num_inh] = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!(in_headers_env = (char **) malloc(2*sizeof(char *))))
|
||||
die(NO_MEMORY,"get_mime_headers",out);
|
||||
in_headers_env[num_inh++] = make_env_str(w,l,out);
|
||||
in_headers_env[num_inh] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dump_default_header(FILE *fd) {
|
||||
fprintf(fd,"Date: %s%c",gm_timestr_822(time(NULL)),LF);
|
||||
fprintf(fd,"Server: %s%c",SERVER_VERSION,LF);
|
||||
@ -299,7 +416,17 @@ void dump_default_header(FILE *fd) {
|
||||
}
|
||||
|
||||
void send_http_header(FILE *fd) {
|
||||
begin_http_header(fd,(location[0] ? "302 Found" : "200 OK"));
|
||||
if(!status_line) {
|
||||
if(location[0]) {
|
||||
status = 302;
|
||||
status_line = "302 Found";
|
||||
}
|
||||
else {
|
||||
status = 200;
|
||||
status_line = "200 OK";
|
||||
}
|
||||
}
|
||||
begin_http_header(fd,status_line);
|
||||
if(content_type[0])
|
||||
fprintf(fd,"Content-type: %s%c",content_type,LF);
|
||||
if(last_modified[0])
|
||||
@ -309,7 +436,8 @@ void send_http_header(FILE *fd) {
|
||||
if(location[0])
|
||||
fprintf(fd,"Location: %s%c",location,LF);
|
||||
if(content_encoding[0])
|
||||
fprintf(fd,"Content-encoding: %s%c",content_encoding,LF,LF);
|
||||
|
||||
fprintf(fd,"Content-encoding: %s%c",content_encoding,LF);
|
||||
if(out_headers)
|
||||
fprintf(fd,"%s",out_headers);
|
||||
fprintf(fd,"%c",LF);
|
||||
}
|
||||
|
59
src/http_post.c
Normal file
59
src/http_post.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* http_post.c: Handles POST
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
*/
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
void handle_post(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
char ct_bak[MAX_STRING_LEN];
|
||||
|
||||
strcpy(ct_bak,content_type); /* oop ack */
|
||||
if(stat(name,&finfo) == -1) {
|
||||
if(find_script("POST",name,args,in,out))
|
||||
return;
|
||||
if(errno==ENOENT) {
|
||||
log_reason("file does not exist",name);
|
||||
unmunge_name(name);
|
||||
die(NOT_FOUND,name,out);
|
||||
}
|
||||
else {
|
||||
log_reason("file permissions deny server access",name);
|
||||
unmunge_name(name);
|
||||
die(FORBIDDEN,name,out);
|
||||
}
|
||||
}
|
||||
probe_content_type(name);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
|
||||
strcpy(content_type,ct_bak);
|
||||
send_cgi("POST",name,"",args,&finfo,in,out);
|
||||
return;
|
||||
}
|
||||
/* Not a script, do group ann thang */
|
||||
die(NOT_IMPLEMENTED,"POST to non-script",out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void post_node(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
int s;
|
||||
|
||||
s=translate_name(name,out);
|
||||
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
handle_post(name,args,in,out);
|
||||
return;
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,name,out);
|
||||
case SCRIPT_NCSA:
|
||||
exec_post_NCSA(name,args,in,out);
|
||||
return;
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script("POST",name,args,in,out);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* http_put.c: Handles PUT and POST
|
||||
* http_put.c: Handles PUT
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
@ -7,8 +7,38 @@
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
void handle_put(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
char ct_bak[MAX_STRING_LEN];
|
||||
|
||||
void get_node(char *name, char *args, int in, FILE *out) {
|
||||
strcpy(ct_bak,content_type); /* oop ack */
|
||||
if(stat(name,&finfo) == -1) {
|
||||
if(find_script("PUT",name,args,in,out))
|
||||
return;
|
||||
if(errno==ENOENT) {
|
||||
log_reason("file does not exist",name);
|
||||
unmunge_name(name);
|
||||
die(NOT_FOUND,name,out);
|
||||
}
|
||||
else {
|
||||
log_reason("file permissions deny server access",name);
|
||||
unmunge_name(name);
|
||||
die(FORBIDDEN,name,out);
|
||||
}
|
||||
}
|
||||
probe_content_type(name);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
|
||||
strcpy(content_type,ct_bak);
|
||||
send_cgi("PUT",name,"",args,&finfo,in,out);
|
||||
return;
|
||||
}
|
||||
/* Not a script, do group ann thang */
|
||||
die(NOT_IMPLEMENTED,"PUT to non-script",out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void put_node(char *name, char *args, int in, FILE *out) {
|
||||
struct stat finfo;
|
||||
int s;
|
||||
|
||||
@ -16,14 +46,13 @@ void get_node(char *name, char *args, int in, FILE *out) {
|
||||
|
||||
switch(s) {
|
||||
case STD_DOCUMENT:
|
||||
die(NOT_IMPLEMENTED,
|
||||
"POST access to area not configured as script area",out);
|
||||
handle_put(name,args,in,out);
|
||||
return;
|
||||
case REDIRECT_URL:
|
||||
die(REDIRECT,name,out);
|
||||
case SCRIPT_NCSA:
|
||||
exec_post_NCSA(name,args,in,out);
|
||||
return;
|
||||
case SCRIPT_CGI:
|
||||
exec_cgi_script("POST",name,args,in,out);
|
||||
exec_cgi_script("PUT",name,args,in,out);
|
||||
default:
|
||||
die(NOT_IMPLEMENTED,"NCSA script exeuction of delete",out);
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,11 @@
|
||||
*
|
||||
* Rob McCool 3/21/93
|
||||
*
|
||||
* Include code by Charles Henrich
|
||||
*/
|
||||
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
#define OUTBUFSIZE 1024
|
||||
|
||||
int assbackwards;
|
||||
char *remote_host;
|
||||
char *remote_ip;
|
||||
@ -18,212 +15,87 @@ char *remote_name;
|
||||
|
||||
/* If RFC931 identity check is on, the remote user name */
|
||||
char *remote_logname;
|
||||
|
||||
/*
|
||||
* Thanks to Charles Henrich
|
||||
*/
|
||||
void process_include(FILE *f, FILE *fd, char *incstring, char *args)
|
||||
{
|
||||
FILE *ifp;
|
||||
char srcfile[HUGE_STRING_LEN];
|
||||
char command[HUGE_STRING_LEN];
|
||||
char errstr[MAX_STRING_LEN];
|
||||
char cmd[10];
|
||||
|
||||
if(sscanf(incstring,"%s \"%[^\"]", cmd, srcfile) != 2) {
|
||||
sprintf(errstr,"the include string %s was invalid",incstring);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
|
||||
if(strncasecmp(cmd,"srv",3) != 0) {
|
||||
fprintf(fd, "%s\r\n",cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if(srcfile[0] != '|') {
|
||||
if(num_includes > MAXINCLUDES) {
|
||||
die(INCLUDE_ERROR,
|
||||
"the maximum number of includes has been exceeded",fd);
|
||||
}
|
||||
|
||||
num_includes++;
|
||||
|
||||
if(translate_name(srcfile,fd) != 0)
|
||||
die(INCLUDE_ERROR,"non-standard file include",fd);
|
||||
ifp=fopen(srcfile,"r");
|
||||
|
||||
if(ifp != NULL) {
|
||||
send_fd(ifp, fd, "");
|
||||
fclose(ifp);
|
||||
}
|
||||
else {
|
||||
sprintf(errstr,"the include file %s was invalid",srcfile);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifndef PEM_AUTH
|
||||
escape_shell_cmd(&srcfile[1]);
|
||||
if(strncasecmp(cmd,"srvurl",6) == 0) {
|
||||
escape_shell_cmd(args);
|
||||
sprintf(command,"%s '%s'",&srcfile[1],args);
|
||||
}
|
||||
else {
|
||||
strcpy(command,&srcfile[1]);
|
||||
}
|
||||
|
||||
ifp=popen(command,"r");
|
||||
|
||||
if(ifp != NULL) {
|
||||
send_fd(ifp, fd, args);
|
||||
pclose(ifp);
|
||||
}
|
||||
else {
|
||||
sprintf(errstr,"the command %s is invalid",&srcfile[1]);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
#else
|
||||
int pid,p[2];
|
||||
|
||||
/* This is done because popen() seems to wait for the wrong */
|
||||
/* child process when encryption is being used. Suggestions */
|
||||
/* are welcome. */
|
||||
|
||||
if(pipe(p) == -1)
|
||||
die(SERVER_ERROR,"Could not create an IPC pipe",fd);
|
||||
if((pid = fork()) == -1)
|
||||
die(SERVER_ERROR,"Could not fork a new process",fd);
|
||||
if(!pid) {
|
||||
char *argv0;
|
||||
char *cmd;
|
||||
|
||||
cmd = &srcfile[1];
|
||||
if(!(argv0 = strrchr(cmd,'/')))
|
||||
argv0 = cmd;
|
||||
else
|
||||
argv0++;
|
||||
close(p[0]);
|
||||
if(p[1] != STDOUT_FILENO) {
|
||||
dup2(p[1],STDOUT_FILENO);
|
||||
close(p[1]);
|
||||
}
|
||||
if(strncasecmp(cmd,"srvurl",6) == 0) {
|
||||
escape_shell_cmd(args);
|
||||
if(execlp(cmd,argv0,args,(char *)0) == -1) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"could not execute included pgm %s",cmd);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(execlp(cmd,argv0,(char *)0) == -1) {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"could not execute included pgm %s",cmd);
|
||||
die(INCLUDE_ERROR,errstr,fd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
close(p[1]);
|
||||
if(!(ifp = fdopen(p[0],"r")))
|
||||
die(INCLUDE_ERROR,"could not open stream to include pipe",fd);
|
||||
send_fd(ifp,fd,args);
|
||||
fclose(ifp);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
static void (*exit_callback)();
|
||||
|
||||
void send_fd_timed_out() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
|
||||
if(exit_callback) (*exit_callback)();
|
||||
sprintf(errstr,"httpd: send timed out for %s",remote_host);
|
||||
log_error(errstr);
|
||||
log_transaction();
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void send_fd(FILE *f, FILE *fd, char *args)
|
||||
void send_fd(FILE *f, FILE *fd, void (*onexit)())
|
||||
{
|
||||
int num_chars=0;
|
||||
char c;
|
||||
struct stat finfo;
|
||||
char buf[IOBUFSIZE];
|
||||
register int n,o,w;
|
||||
|
||||
exit_callback = onexit;
|
||||
signal(SIGALRM,send_fd_timed_out);
|
||||
signal(SIGPIPE,send_fd_timed_out);
|
||||
|
||||
if((allow_options & OPT_INCLUDES) && is_content_type("text/html")) {
|
||||
char *find="<inc";
|
||||
char incstring[MAX_STRING_LEN];
|
||||
int x,p;
|
||||
|
||||
p=0;
|
||||
while(1) {
|
||||
alarm(timeout);
|
||||
c = fgetc(f);
|
||||
if(feof(f))
|
||||
return;
|
||||
if(tolower(c) == find[p]) {
|
||||
if((++p) == 4) {
|
||||
x=0;
|
||||
c=fgetc(f); /* get the space instead of the c */
|
||||
while(c != '>') {
|
||||
incstring[x++] = c;
|
||||
c = fgetc(f);
|
||||
if(feof(f)) {
|
||||
incstring[x] = '\0';
|
||||
fputs("<inc",fd);
|
||||
fputs(incstring,fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
incstring[x] = '\0';
|
||||
process_include(f,fd,incstring,args);
|
||||
p=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(p) {
|
||||
for(x=0;x<p;x++)
|
||||
fputc(find[x],fd);
|
||||
p=0;
|
||||
}
|
||||
fputc(c,fd);
|
||||
}
|
||||
while (1) {
|
||||
alarm(timeout);
|
||||
if((n=fread(buf,sizeof(char),IOBUFSIZE,f)) < 1) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char buf[OUTBUFSIZE];
|
||||
register int n,o,w;
|
||||
|
||||
while (1) {
|
||||
alarm(timeout);
|
||||
if((n=fread(buf,sizeof(char),OUTBUFSIZE,f)) < 1) {
|
||||
break;
|
||||
}
|
||||
o=0;
|
||||
while(n) {
|
||||
w=fwrite(&buf[o],sizeof(char),n,fd);
|
||||
n-=w;
|
||||
o+=w;
|
||||
}
|
||||
o=0;
|
||||
if(bytes_sent != -1)
|
||||
bytes_sent += n;
|
||||
while(n) {
|
||||
w=fwrite(&buf[o],sizeof(char),n,fd);
|
||||
n-=w;
|
||||
o+=w;
|
||||
}
|
||||
}
|
||||
fflush(fd);
|
||||
}
|
||||
|
||||
int find_script(char *method, char *name, char *args, int in, FILE *out)
|
||||
{
|
||||
int n=count_dirs(name),i;
|
||||
char t[HUGE_STRING_LEN],ct_bak[MAX_STRING_LEN];
|
||||
struct stat finfo;
|
||||
|
||||
strcpy(ct_bak,content_type);
|
||||
for(i=n;i;--i) {
|
||||
make_dirstr(name,i,t);
|
||||
probe_content_type(t);
|
||||
if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
|
||||
char pa[HUGE_STRING_LEN];
|
||||
int l=strlen(t);
|
||||
|
||||
if(stat(t,&finfo) == -1)
|
||||
continue;
|
||||
if(!(S_ISREG(finfo.st_mode)))
|
||||
return 0;
|
||||
strcpy(pa,&name[l]);
|
||||
name[l] = '\0';
|
||||
strcpy(content_type,ct_bak);
|
||||
send_cgi(method,name,pa,args,&finfo,in,out);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void process_request(int in, FILE *out) {
|
||||
char m[HUGE_STRING_LEN];
|
||||
char w[HUGE_STRING_LEN];
|
||||
char l[HUGE_STRING_LEN];
|
||||
char url[HUGE_STRING_LEN];
|
||||
char args[HUGE_STRING_LEN];
|
||||
#ifdef HENRICHS_SILLY_HACK
|
||||
char tmpargs[HUGE_STRING_LEN];
|
||||
#endif
|
||||
int s,n;
|
||||
|
||||
get_remote_host(in);
|
||||
exit_callback = NULL;
|
||||
signal(SIGPIPE,send_fd_timed_out);
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
doing_pem = -1;
|
||||
handle_request:
|
||||
@ -234,32 +106,21 @@ void process_request(int in, FILE *out) {
|
||||
if(!l[0])
|
||||
return;
|
||||
|
||||
#ifdef PEM_AUTH
|
||||
if(doing_pem == -1)
|
||||
#endif
|
||||
log_transaction(l);
|
||||
record_request(l);
|
||||
getword(m,l,' ');
|
||||
getword(args,l,' ');
|
||||
#ifdef HENRICHS_SILLY_HACK
|
||||
strcpy(tmpargs,args);
|
||||
getword(url,tmpargs,';');
|
||||
if(!tempargs[0])
|
||||
getword(url,args,'?');
|
||||
else
|
||||
strcpy(args,tmpargs);
|
||||
#else
|
||||
getword(url,args,'?');
|
||||
#endif
|
||||
plustospace(url);
|
||||
/* plustospace(url); */
|
||||
unescape_url(url);
|
||||
getword(w,l,'\0');
|
||||
init_header_vars();
|
||||
if(w[0] != '\0') {
|
||||
assbackwards = 0;
|
||||
get_mime_headers(in);
|
||||
get_mime_headers(in,out);
|
||||
}
|
||||
else
|
||||
assbackwards = 1;
|
||||
|
||||
|
||||
if(!strcmp(m,"HEAD")) {
|
||||
header_only=1;
|
||||
process_get(in,out,m,url,args);
|
||||
@ -269,7 +130,7 @@ void process_request(int in, FILE *out) {
|
||||
if(!assbackwards) {
|
||||
if(doing_pem == -1) {
|
||||
int s2;
|
||||
s2 = pem_decrypt(in,url,&out);
|
||||
s2 = decrypt_request(in,url,&out);
|
||||
if(s2 != -1) {
|
||||
in = s2;
|
||||
content_type[0] = '\0';
|
||||
@ -283,7 +144,15 @@ void process_request(int in, FILE *out) {
|
||||
}
|
||||
else if(!strcmp(m,"POST")) {
|
||||
header_only = 0;
|
||||
get_node(url,args,in,out);
|
||||
post_node(url,args,in,out);
|
||||
}
|
||||
else if(!strcmp(m,"PUT")) {
|
||||
header_only = 0;
|
||||
put_node(url,args,in,out);
|
||||
}
|
||||
else if(!strcmp(m,"DELETE")) {
|
||||
header_only = 0;
|
||||
delete_node(url,args,in,out);
|
||||
}
|
||||
else
|
||||
die(BAD_REQUEST,"Invalid or unsupported method.",out);
|
||||
|
@ -9,11 +9,24 @@
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
int pid;
|
||||
|
||||
void kill_children() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
sprintf(errstr,"killing CGI process %d",pid);
|
||||
log_error_noclose(errstr);
|
||||
|
||||
kill(pid,SIGTERM);
|
||||
sleep(5); /* give them time to clean up */
|
||||
kill(pid,SIGKILL);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
|
||||
char **create_argv(char *av0, char *args, FILE *out) {
|
||||
register int x,n;
|
||||
char **av;
|
||||
char w[MAX_STRING_LEN];
|
||||
char l[MAX_STRING_LEN];
|
||||
char w[HUGE_STRING_LEN];
|
||||
char l[HUGE_STRING_LEN];
|
||||
|
||||
for(x=0,n=2;args[x];x++)
|
||||
if(args[x] == '+') ++n;
|
||||
@ -37,7 +50,7 @@ void get_path_info(char *path, char *path_args, FILE *out,
|
||||
struct stat *finfo)
|
||||
{
|
||||
register int x,max;
|
||||
char t[MAX_STRING_LEN];
|
||||
char t[HUGE_STRING_LEN];
|
||||
|
||||
path_args[0] = '\0';
|
||||
max=count_dirs(path);
|
||||
@ -45,8 +58,9 @@ void get_path_info(char *path, char *path_args, FILE *out,
|
||||
make_dirstr(path,x+1,t);
|
||||
if(!(stat(t,finfo))) {
|
||||
if(S_ISREG(finfo->st_mode)) {
|
||||
strcpy(path_args,&path[strlen(t)]);
|
||||
strcpy(path,t);
|
||||
int l=strlen(t);
|
||||
strcpy(path_args,&path[l]);
|
||||
path[l] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -65,82 +79,96 @@ void get_path_info(char *path, char *path_args, FILE *out,
|
||||
die(NOT_FOUND,path,out);
|
||||
}
|
||||
|
||||
#define MAX_CGI_VARS 18
|
||||
#define MAX_COMMON_VARS 9
|
||||
#define MAX_CGI_VARS (MAX_COMMON_VARS+9)
|
||||
|
||||
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
char **add_cgi_vars(char **env,
|
||||
char *method, char *path, char *path_args, char *args,
|
||||
int *content,
|
||||
FILE *out)
|
||||
{
|
||||
int pid, p[2];
|
||||
int content, nph;
|
||||
char cl[MAX_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
|
||||
char path_args[MAX_STRING_LEN];
|
||||
char *argv0,**env;
|
||||
FILE *psin;
|
||||
struct stat finfo;
|
||||
register int n,x;
|
||||
int x;
|
||||
char t[HUGE_STRING_LEN],t2[HUGE_STRING_LEN];
|
||||
|
||||
get_path_info(path,path_args,out,&finfo);
|
||||
|
||||
if(!can_exec(&finfo)) {
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
if(!(env = new_env(env,MAX_CGI_VARS,&x)))
|
||||
die(NO_MEMORY,"add_cgi_vars",out);
|
||||
|
||||
/* BAD -- method specific */
|
||||
evaluate_access(path,&finfo,((!strcmp(method,"POST")) ? M_POST : M_GET),
|
||||
&allow,&allow_options,out);
|
||||
if(!allow) {
|
||||
log_reason("client denied by server configuration",path);
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
env[x++] = make_env_str("GATEWAY_INTERFACE","CGI/1.1",out);
|
||||
|
||||
if(!(env = (char **)malloc((MAX_CGI_VARS + 2) * sizeof(char *))))
|
||||
die(NO_MEMORY,"exec_cgi_script",out);
|
||||
n = 0;
|
||||
env[n++] = make_env_str("PATH",getenv("PATH"),out);
|
||||
env[n++] = make_env_str("SERVER_SOFTWARE",SERVER_VERSION,out);
|
||||
env[n++] = make_env_str("SERVER_NAME",server_hostname,out);
|
||||
env[n++] = make_env_str("GATEWAY_INTERFACE","CGI/1.0",out);
|
||||
|
||||
sprintf(t,"%d",port);
|
||||
env[n++] = make_env_str("SERVER_PORT",t,out);
|
||||
|
||||
env[n++] = make_env_str("SERVER_PROTOCOL",
|
||||
env[x++] = make_env_str("SERVER_PROTOCOL",
|
||||
(assbackwards ? "HTTP/0.9" : "HTTP/1.0"),out);
|
||||
env[n++] = make_env_str("REQUEST_METHOD",method,out);
|
||||
env[n++] = make_env_str("HTTP_ACCEPT",http_accept,out);
|
||||
if(path_args[0]) {
|
||||
env[n++] = make_env_str("PATH_INFO",path_args,out);
|
||||
strcpy(t2,path_args);
|
||||
translate_name(t2,out);
|
||||
env[n++] = make_env_str("PATH_TRANSLATED",t2,out);
|
||||
}
|
||||
env[x++] = make_env_str("REQUEST_METHOD",method,out);
|
||||
|
||||
strcpy(t,path);
|
||||
unmunge_name(t);
|
||||
env[n++] = make_env_str("SCRIPT_NAME",t,out);
|
||||
env[n++] = make_env_str("QUERY_STRING",args,out);
|
||||
env[n++] = make_env_str("REMOTE_HOST",remote_name,out);
|
||||
env[n++] = make_env_str("REMOTE_ADDR",remote_ip,out);
|
||||
if(user[0])
|
||||
env[n++] = make_env_str("REMOTE_USER",user,out);
|
||||
if(auth_type)
|
||||
env[n++] = make_env_str("AUTH_TYPE",auth_type,out);
|
||||
|
||||
if(do_rfc931)
|
||||
env[n++] = make_env_str("REMOTE_IDENT",remote_logname,out);
|
||||
content=0;
|
||||
if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
|
||||
content=1;
|
||||
sprintf(cl,"%d",content_length);
|
||||
env[n++] = make_env_str("CONTENT_TYPE",content_type,out);
|
||||
env[n++] = make_env_str("CONTENT_LENGTH",cl,out);
|
||||
env[x++] = make_env_str("SCRIPT_NAME",t,out);
|
||||
if(path_args[0]) {
|
||||
env[x++] = make_env_str("PATH_INFO",path_args,out);
|
||||
strcpy(t2,path_args);
|
||||
translate_name(t2,out);
|
||||
env[x++] = make_env_str("PATH_TRANSLATED",t2,out);
|
||||
}
|
||||
env[x++] = make_env_str("QUERY_STRING",args,out);
|
||||
|
||||
if(content) {
|
||||
*content=0;
|
||||
if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
|
||||
*content=1;
|
||||
sprintf(t,"%d",content_length);
|
||||
env[x++] = make_env_str("CONTENT_TYPE",content_type,out);
|
||||
env[x++] = make_env_str("CONTENT_LENGTH",t,out);
|
||||
}
|
||||
}
|
||||
env[x] = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
char **add_common_vars(char **env,FILE *out) {
|
||||
char t[HUGE_STRING_LEN],*env_path;
|
||||
int x;
|
||||
|
||||
if(!(env = new_env(env,MAX_COMMON_VARS,&x)))
|
||||
die(NO_MEMORY,"add_common_vars",out);
|
||||
|
||||
if(!(env_path = getenv("PATH")))
|
||||
env_path=DEFAULT_PATH;
|
||||
env[x++] = make_env_str("PATH",env_path,out);
|
||||
env[x++] = make_env_str("SERVER_SOFTWARE",SERVER_VERSION,out);
|
||||
env[x++] = make_env_str("SERVER_NAME",server_hostname,out);
|
||||
sprintf(t,"%d",port);
|
||||
env[x++] = make_env_str("SERVER_PORT",t,out);
|
||||
env[x++] = make_env_str("REMOTE_HOST",remote_name,out);
|
||||
env[x++] = make_env_str("REMOTE_ADDR",remote_ip,out);
|
||||
if(user[0])
|
||||
env[x++] = make_env_str("REMOTE_USER",user,out);
|
||||
if(auth_type)
|
||||
env[x++] = make_env_str("AUTH_TYPE",auth_type,out);
|
||||
if(do_rfc931)
|
||||
env[x++] = make_env_str("REMOTE_IDENT",remote_logname,out);
|
||||
env[x] = NULL;
|
||||
return env;
|
||||
}
|
||||
|
||||
int cgi_stub(char *method, char *path, char *path_args, char *args,
|
||||
char **env, struct stat *finfo, int in, FILE *out)
|
||||
{
|
||||
int p[2];
|
||||
int content, nph;
|
||||
char *argv0;
|
||||
FILE *psin;
|
||||
register int x;
|
||||
|
||||
if(!can_exec(finfo)) {
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
env[n] = NULL;
|
||||
|
||||
if((argv0 = strrchr(path,'/')) != NULL)
|
||||
argv0++;
|
||||
else argv0 = path;
|
||||
|
||||
chdir_file(path);
|
||||
|
||||
if(pipe(p) < 0)
|
||||
die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
|
||||
if((pid = fork()) < 0)
|
||||
@ -148,6 +176,8 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
|
||||
nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
|
||||
if(!pid) {
|
||||
close(p[0]);
|
||||
env = add_cgi_vars(env,method,path,path_args,args,&content,out);
|
||||
if(content)
|
||||
if(in != STDIN_FILENO) {
|
||||
dup2(in,STDIN_FILENO);
|
||||
@ -164,6 +194,7 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
close(p[1]);
|
||||
}
|
||||
}
|
||||
error_log2stderr();
|
||||
/* Only ISINDEX scripts get decoded arguments. */
|
||||
if((!args[0]) || (ind(args,'=') >= 0)) {
|
||||
if(execle(path,argv0,(char *)0,env) == -1) {
|
||||
@ -181,9 +212,6 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(x=0;x<n;x++)
|
||||
free(env[n]);
|
||||
free(env);
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
@ -191,33 +219,69 @@ void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
if(!(psin = fdopen(p[0],"r")))
|
||||
die(SERVER_ERROR,"could not read from script",out);
|
||||
|
||||
if(scan_script_header(psin,out))
|
||||
die(REDIRECT,location,out);
|
||||
if(scan_script_header(psin,out)) {
|
||||
kill_children(); /* !!! */
|
||||
return REDIRECT_URL;
|
||||
}
|
||||
|
||||
if(location[0] == '/') {
|
||||
char t[MAX_STRING_LEN],a[MAX_STRING_LEN],*argp;
|
||||
char t[HUGE_STRING_LEN],a[HUGE_STRING_LEN],*argp;
|
||||
|
||||
a[0] = '\0';
|
||||
fclose(psin);
|
||||
waitpid(pid,NULL,0);
|
||||
strcpy(t,location);
|
||||
location[0] = '\0';
|
||||
if(argp = strchr(t,'?')) {
|
||||
*argp++ = '\0';
|
||||
strcpy(a,argp);
|
||||
}
|
||||
process_get(in,out,method,t,a);
|
||||
return;
|
||||
init_header_vars(); /* clear in_header_env and location */
|
||||
process_get(in,out,"GET",t,a);
|
||||
return 0;
|
||||
}
|
||||
content_length = -1;
|
||||
if(!assbackwards)
|
||||
send_http_header(out);
|
||||
if(!header_only)
|
||||
send_fd(psin,out,args);
|
||||
/* This will cause SIGPIPE in child... it should terminate */
|
||||
send_fd(psin,out,kill_children);
|
||||
else
|
||||
kill_children();
|
||||
fclose(psin);
|
||||
}
|
||||
else bytes_sent = -1;
|
||||
waitpid(pid,NULL,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called for ScriptAliased directories */
|
||||
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
|
||||
{
|
||||
struct stat finfo;
|
||||
char path_args[HUGE_STRING_LEN];
|
||||
char **env;
|
||||
int m;
|
||||
|
||||
get_path_info(path,path_args,out,&finfo);
|
||||
if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD"))) m=M_GET;
|
||||
else if(!strcmp(method,"POST")) m=M_POST;
|
||||
else if(!strcmp(method,"PUT")) m=M_PUT;
|
||||
else if(!strcmp(method,"DELETE")) m=M_DELETE;
|
||||
|
||||
evaluate_access(path,&finfo,m,&allow,&allow_options,out);
|
||||
if(!allow) {
|
||||
log_reason("client denied by server configuration",path);
|
||||
unmunge_name(path);
|
||||
die(FORBIDDEN,path,out);
|
||||
}
|
||||
if(!(env = add_common_vars(in_headers_env,out)))
|
||||
die(NO_MEMORY,"exec_cgi_script",out);
|
||||
|
||||
bytes_sent = 0;
|
||||
if(cgi_stub(method,path,path_args,args,env,&finfo,in,out) == REDIRECT_URL)
|
||||
die(REDIRECT,location,out);
|
||||
/* cgi_stub will screw with env, but only after the fork */
|
||||
free_env(env);
|
||||
log_transaction();
|
||||
}
|
||||
|
||||
char **set_env_NCSA(FILE *out) {
|
||||
@ -240,10 +304,10 @@ char **set_env_NCSA(FILE *out) {
|
||||
return env;
|
||||
}
|
||||
|
||||
void exec_get_NCSA(char *path, char *args, FILE *fd) {
|
||||
void exec_get_NCSA(char *path, char *args, int in, FILE *fd) {
|
||||
FILE *tfp;
|
||||
struct stat finfo;
|
||||
int pid,pfd[2];
|
||||
int pfd[2];
|
||||
char path_args[MAX_STRING_LEN];
|
||||
char t[MAX_STRING_LEN];
|
||||
register int n,x;
|
||||
@ -329,7 +393,7 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
|
||||
if(!(t = strdup(location)))
|
||||
die(NO_MEMORY,"exec_get_NCSA",fd);
|
||||
location[0] = '\0';
|
||||
send_node(t,"",fd);
|
||||
send_node(t,"",in,fd);
|
||||
htexit(0,fd);
|
||||
}
|
||||
|
||||
@ -337,7 +401,9 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
|
||||
send_http_header(fd);
|
||||
|
||||
if(!header_only)
|
||||
send_fd(tfp,fd,args);
|
||||
send_fd(tfp,fd,kill_children);
|
||||
else
|
||||
kill_children();
|
||||
fclose(tfp);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
@ -345,7 +411,7 @@ void exec_get_NCSA(char *path, char *args, FILE *fd) {
|
||||
|
||||
|
||||
void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
|
||||
int pid, inpipe[2],outpipe[2], x;
|
||||
int inpipe[2],outpipe[2], x;
|
||||
char cl[MAX_STRING_LEN];
|
||||
FILE *psin,*psout;
|
||||
struct stat finfo;
|
||||
@ -404,7 +470,7 @@ void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
|
||||
if(!(t = strdup(location)))
|
||||
die(NO_MEMORY,"exec_post_NCSA",out);
|
||||
location[0] = '\0';
|
||||
send_node(t,"",out);
|
||||
send_node(t,"",in,out);
|
||||
htexit(0,out);
|
||||
}
|
||||
|
||||
@ -412,7 +478,7 @@ void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
|
||||
if(!assbackwards)
|
||||
send_http_header(out);
|
||||
|
||||
send_fd(psin,out,args);
|
||||
send_fd(psin,out,kill_children);
|
||||
fclose(psin);
|
||||
waitpid(pid,NULL,0);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ void seg_fault() {
|
||||
void set_signals();
|
||||
|
||||
void restart() {
|
||||
log_error("httpd: caught SIGHUP, restarting");
|
||||
log_error_noclose("httpd: caught SIGHUP, restarting");
|
||||
kill_mime();
|
||||
kill_security();
|
||||
kill_indexing();
|
||||
@ -99,10 +99,10 @@ void restart() {
|
||||
free(server_hostname);
|
||||
server_hostname = NULL;
|
||||
}
|
||||
read_config();
|
||||
read_config(error_log);
|
||||
close_logs();
|
||||
open_logs();
|
||||
log_error("httpd: successful restart");
|
||||
log_error_noclose("httpd: successful restart");
|
||||
get_local_host();
|
||||
set_signals();
|
||||
}
|
||||
@ -245,7 +245,7 @@ main(int argc, char *argv[])
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
read_config();
|
||||
read_config(stderr);
|
||||
open_logs();
|
||||
get_local_host();
|
||||
|
||||
@ -254,6 +254,7 @@ main(int argc, char *argv[])
|
||||
else {
|
||||
user_id = getuid();
|
||||
group_id = getgid();
|
||||
|
||||
port = get_portnum(fileno(stdout),stdout);
|
||||
if(do_rfc931)
|
||||
remote_logname = get_remote_logname(stdout);
|
||||
|
141
src/httpd.h
141
src/httpd.h
@ -25,7 +25,10 @@ char *crypt(char *pw, char *salt);
|
||||
#undef BSD
|
||||
#define NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
#ifndef _HPUX_SOURCE
|
||||
#define _HPUX_SOURCE
|
||||
#endif
|
||||
#define getwd(d) getcwd(d,MAX_STRING_LEN)
|
||||
|
||||
#elif defined(AIX)
|
||||
#undef BSD
|
||||
@ -115,6 +118,11 @@ typedef int pid_t;
|
||||
#define NEED_STRNCASECMP
|
||||
#define bzero(a,b) memset(a,0,b)
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
#define BSD
|
||||
#undef NO_KILLPG
|
||||
#undef NO_SETSID
|
||||
|
||||
/* Unknown system - Edit these to match */
|
||||
#else
|
||||
/* BSD is whether your system uses BSD calls or System V calls. */
|
||||
@ -134,6 +142,9 @@ typedef int pid_t;
|
||||
* /usr/include/sys/dir.h, define DIR_TYPE to be direct and include that
|
||||
* file. If you have neither, I'm confused.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(NEXT) && !defined(CONVEXOS)
|
||||
#include <dirent.h>
|
||||
#define DIR_TYPE dirent
|
||||
@ -158,9 +169,6 @@ typedef int pid_t;
|
||||
/* Max. number of security defines */
|
||||
#define MAX_SECURITY 50
|
||||
|
||||
/* Max. number of include files */
|
||||
#define MAXINCLUDES 20
|
||||
|
||||
/* Default administrator's address */
|
||||
#define DEFAULT_ADMIN "[no address given]"
|
||||
|
||||
@ -218,6 +226,11 @@ typedef int pid_t;
|
||||
/* The default directory in user's home dir */
|
||||
#define DEFAULT_USER_DIR "public_html"
|
||||
|
||||
/* The default path for CGI scripts if none is currently set */
|
||||
#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
|
||||
|
||||
/* The path to the Bourne shell, for parsed docs */
|
||||
#define SHELL_PATH "/bin/sh"
|
||||
|
||||
/* The default string lengths */
|
||||
#define MAX_STRING_LEN 256
|
||||
@ -226,28 +239,34 @@ typedef int pid_t;
|
||||
/* The timeout for waiting for messages */
|
||||
#define DEFAULT_TIMEOUT 1200
|
||||
|
||||
/* The size of the server's internal read-write buffers */
|
||||
#define IOBUFSIZE 8192
|
||||
|
||||
/* The number of header lines we will accept from a client */
|
||||
#define MAX_HEADERS 200
|
||||
|
||||
/* ------------------------------ error types ------------------------------ */
|
||||
|
||||
#define SERVER_VERSION "NCSA/1.1"
|
||||
#define SERVER_VERSION "NCSA/1.2"
|
||||
#define SERVER_PROTOCOL "HTTP/1.0"
|
||||
#define SERVER_SUPPORT "httpd@ncsa.uiuc.edu"
|
||||
|
||||
#define DOCUMENT_FOLLOWS 200
|
||||
#define REDIRECT 302
|
||||
#define USE_LOCAL_COPY 304
|
||||
#define BAD_REQUEST 400
|
||||
#define AUTH_REQUIRED 401
|
||||
#define FORBIDDEN 403
|
||||
#define NOT_FOUND 404
|
||||
#define SERVER_ERROR 500
|
||||
#define NOT_IMPLEMENTED 501
|
||||
#define INCLUDE_ERROR 6991
|
||||
#define NO_MEMORY 6992
|
||||
|
||||
#define METHODS 3
|
||||
#define METHODS 4
|
||||
#define M_GET 0
|
||||
#define M_PUT 1
|
||||
#define M_POST 2
|
||||
#define M_DELETE 3
|
||||
|
||||
/* Object types */
|
||||
#define REDIRECT_URL -1
|
||||
@ -259,21 +278,35 @@ typedef int pid_t;
|
||||
#define OPT_INDEXES 1
|
||||
#define OPT_INCLUDES 2
|
||||
#define OPT_SYM_LINKS 4
|
||||
#define OPT_UNSET 8
|
||||
#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS)
|
||||
#define OPT_EXECCGI 8
|
||||
#define OPT_UNSET 16
|
||||
#define OPT_INCNOEXEC 32
|
||||
#define OPT_SYM_OWNER 64
|
||||
#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_SYM_LINKS|OPT_EXECCGI)
|
||||
|
||||
#define OR_NONE 0
|
||||
#define OR_LIMIT 1
|
||||
#define OR_OPTIONS 2
|
||||
#define OR_FILEINFO 4
|
||||
#define OR_AUTHCFG 16
|
||||
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG)
|
||||
#define OR_AUTHCFG 8
|
||||
#define OR_INDEXES 16
|
||||
#define OR_ALL (OR_LIMIT|OR_OPTIONS|OR_FILEINFO|OR_AUTHCFG|OR_INDEXES)
|
||||
|
||||
#define CGI_MAGIC_TYPE "application/x-httpd-cgi"
|
||||
#define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html"
|
||||
|
||||
/* For directory indexing */
|
||||
#define BY_PATH 0
|
||||
#define BY_TYPE 1
|
||||
#define BY_ENCODING 2
|
||||
|
||||
#define FANCY_INDEXING 1
|
||||
#define ICONS_ARE_LINKS 2
|
||||
#define SCAN_HTML_TITLES 4
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
@ -305,6 +338,7 @@ typedef int pid_t;
|
||||
/* For access control */
|
||||
#define DENY_THEN_ALLOW 0
|
||||
#define ALLOW_THEN_DENY 1
|
||||
#define MUTUAL_FAILURE 2
|
||||
|
||||
/* Struct shared by access and auth */
|
||||
typedef struct {
|
||||
@ -328,7 +362,7 @@ typedef struct {
|
||||
char *deny[METHODS][MAX_SECURITY];
|
||||
} security_data;
|
||||
|
||||
/* Globals */
|
||||
/* Global, global, who's got the globals? */
|
||||
|
||||
/* Server config */
|
||||
extern int standalone;
|
||||
@ -363,6 +397,7 @@ extern char access_name[MAX_STRING_LEN];
|
||||
extern char document_root[MAX_STRING_LEN];
|
||||
extern char default_type[MAX_STRING_LEN];
|
||||
extern char default_icon[MAX_STRING_LEN];
|
||||
extern char blank_icon[MAX_STRING_LEN];
|
||||
extern int fancy_indexing;
|
||||
extern char readme_fname[MAX_STRING_LEN];
|
||||
|
||||
@ -396,14 +431,21 @@ extern int dirs_in_alias;
|
||||
extern char auth_line[MAX_STRING_LEN];
|
||||
extern int content_length;
|
||||
extern char content_type[MAX_STRING_LEN];
|
||||
extern char content_encoding[MAX_STRING_LEN];
|
||||
extern char location[MAX_STRING_LEN];
|
||||
extern char http_accept[HUGE_STRING_LEN];
|
||||
extern char **in_headers_env;
|
||||
|
||||
/* http_log */
|
||||
extern FILE *error_log;
|
||||
extern int bytes_sent;
|
||||
extern int status;
|
||||
|
||||
/* Function prototypes. */
|
||||
|
||||
/* http_config */
|
||||
void read_config();
|
||||
void parse_htaccess(char *dir, char override, FILE *out);
|
||||
int get_pw(char *user, char *pw);
|
||||
int get_pw(char *user, char *pw, FILE *errors);
|
||||
int in_group(char *user, char *group);
|
||||
int init_group(char *grpfile, FILE *out);
|
||||
void kill_group();
|
||||
@ -418,44 +460,69 @@ void unmunge_name(char *name);
|
||||
|
||||
/* http_request */
|
||||
void process_request(int in, FILE *out);
|
||||
void send_fd(FILE *f, FILE *fd, char *args);
|
||||
void send_fd(FILE *f, FILE *fd, void (*callback)());
|
||||
void send_fd_timed_out();
|
||||
int find_script(char *method, char *name, char *args, int in, FILE *out);
|
||||
|
||||
/* http_get */
|
||||
void send_file(char *file,FILE *fd, char *args);
|
||||
void send_file(char *file,FILE *fd, char *path_args, char *args);
|
||||
void process_include(FILE *f, FILE *fd, char *incstring, char *args);
|
||||
void send_node(char *name, char *args, FILE *fd);
|
||||
void send_node(char *name, char *args, int in, FILE *fd);
|
||||
void process_get(int in, FILE *out, char *m, char *url, char *args);
|
||||
|
||||
/* http_post */
|
||||
void post_node(char *name, char *args, int in, FILE *out);
|
||||
|
||||
/* http_put */
|
||||
void get_node(char *name, char *args, int in, FILE *out);
|
||||
void put_node(char *name, char *args, int in, FILE *out);
|
||||
|
||||
/* http_delete */
|
||||
void delete_node(char *name, char *args, int in, FILE *out);
|
||||
|
||||
/* http_script */
|
||||
void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out);
|
||||
void exec_get_NCSA(char *path, char *args, FILE *fd);
|
||||
int cgi_stub(char *method, char *path, char *path_args, char *args,
|
||||
char **env, struct stat *finfo, int in, FILE *out);
|
||||
void exec_get_NCSA(char *path, char *args, int in, FILE *fd);
|
||||
void exec_post_NCSA(char *path, char *args, int in, FILE *out);
|
||||
char **add_common_vars(char **env, FILE *out);
|
||||
void get_path_info(char *path, char *path_args, FILE *out,
|
||||
struct stat *finfo);
|
||||
|
||||
/* http_dir */
|
||||
extern void index_directory(char *name, FILE *fd);
|
||||
extern void add_icon(char *icon, char *ext, FILE *out);
|
||||
extern void add_desc(char *desc, char *ext, FILE *out);
|
||||
extern void add_ignore(char *ext, FILE *out);
|
||||
extern void init_indexing();
|
||||
extern void kill_indexing();
|
||||
void index_directory(char *name, FILE *fd);
|
||||
void add_icon(int type, char *icon, char *to, char *path, FILE *out);
|
||||
void add_alt(int type, char *alt, char *to, char *path, FILE *out);
|
||||
void add_desc(int type, char *desc, char *to, char *path, FILE *out);
|
||||
void add_ignore(char *ext, char *path, FILE *out);
|
||||
void add_header(char *name, char *path, FILE *out);
|
||||
void add_readme(char *name, char *path, FILE *out);
|
||||
void add_opts(char *optstr, char *path, FILE *out);
|
||||
void add_opts_int(int opts, char *path, FILE *out);
|
||||
void send_size(size_t size, FILE *fd);
|
||||
|
||||
void init_indexing();
|
||||
void kill_indexing();
|
||||
|
||||
/* http_log */
|
||||
void log_transaction(char *cmd_line);
|
||||
void record_request(char *cmd_line);
|
||||
void log_error(char *err);
|
||||
void log_error_noclose(char *err);
|
||||
void log_reason(char *reason, char *file);
|
||||
void die(int type, char *err_string, FILE *fd);
|
||||
void open_logs();
|
||||
void close_logs();
|
||||
void begin_http_header(FILE *fd, char *msg);
|
||||
void error_log2stderr();
|
||||
void log_transaction();
|
||||
|
||||
/* http_mime */
|
||||
void get_mime_headers(int fd);
|
||||
void get_mime_headers(int fd, FILE *out);
|
||||
void init_header_vars();
|
||||
void send_http_header(FILE *fd);
|
||||
void set_content_type(char *fn);
|
||||
void set_last_modified(time_t t, FILE *out);
|
||||
void probe_content_type(char *fn);
|
||||
int scan_script_header(FILE *f, FILE *fd);
|
||||
void add_type(char *fn, char *t,FILE *out);
|
||||
void add_encoding(char *fn, char *t,FILE *out);
|
||||
@ -474,15 +541,25 @@ void kill_security();
|
||||
/* http_auth */
|
||||
void check_auth(security_data *s, int m, FILE *out);
|
||||
#ifdef PEM_AUTH
|
||||
int pem_decrypt(int sfd, char *req, FILE **out);
|
||||
int decrypt_request(int sfd, char *req, FILE **out);
|
||||
void htexit(int status, FILE *out);
|
||||
#endif
|
||||
|
||||
/* http_include */
|
||||
void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
|
||||
int noexec);
|
||||
|
||||
/* util */
|
||||
void chdir_file(char *file);
|
||||
void http2cgi(char *w);
|
||||
int later_than(char *l, char *i);
|
||||
int strcmp_match(char *str, char *exp);
|
||||
int is_matchexp(char *str);
|
||||
void strsubfirst(int start,char *dest, char *src);
|
||||
void make_full_path(char *src1,char *src2,char *dst);
|
||||
int is_directory(char *name);
|
||||
void getparents(char *name);
|
||||
void no2slash(char *name);
|
||||
uid_t uname2id(char *name);
|
||||
gid_t gname2id(char *name);
|
||||
int getline(char *s, int n, int f, unsigned int timeout);
|
||||
@ -492,6 +569,8 @@ void cfg_getword(char *word, char *line);
|
||||
void get_remote_host(int fd);
|
||||
char *get_time();
|
||||
char *gm_timestr_822(time_t t);
|
||||
char *ht_time(time_t t, char *fmt, int gmt);
|
||||
struct tm *get_gmtoff(long *tz);
|
||||
void make_dirstr(char *s, int n, char *d);
|
||||
int count_dirs(char *path);
|
||||
void strcpy_dir(char *d, char *s);
|
||||
@ -506,12 +585,14 @@ void uudecode(char *s,unsigned char *d,int dl);
|
||||
char *strdup (char *str);
|
||||
#endif
|
||||
#ifdef NEED_STRCASECMP
|
||||
char *strcasecmp(const char *s1, const char *s2);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
#endif
|
||||
#ifdef NEED_STRNCASECMP
|
||||
char *strncasecmp(const char *s1, const char *s2, int n);
|
||||
int strncasecmp(const char *s1, const char *s2, int n);
|
||||
#endif
|
||||
char *make_env_str(char *n, char *v, FILE *out);
|
||||
char **new_env(char **env, int to_add, int *pos);
|
||||
void free_env(char **env);
|
||||
int ind(char *s, char c);
|
||||
int rind(char *s, char c);
|
||||
void construct_url(char *d, char *s);
|
||||
|
234
src/util.c
234
src/util.c
@ -19,15 +19,139 @@ char *get_time() {
|
||||
}
|
||||
|
||||
char *gm_timestr_822(time_t sec) {
|
||||
struct tm *t;
|
||||
static char ts[MAX_STRING_LEN];
|
||||
/* HUH??? Why is the GMT hardcode necessary? */
|
||||
return ht_time(sec,"%A, %d-%h-%y %T GMT", 1);
|
||||
}
|
||||
|
||||
char *ht_time(time_t t, char *fmt, int gmt) {
|
||||
static char ts[MAX_STRING_LEN];
|
||||
struct tm *tms;
|
||||
|
||||
tms = (gmt ? gmtime(&t) : localtime(&t));
|
||||
|
||||
t = gmtime(&sec);
|
||||
/* check return code? */
|
||||
strftime(ts,MAX_STRING_LEN,"%A, %d-%h-%y %T GMT",t);
|
||||
strftime(ts,MAX_STRING_LEN,fmt,tms);
|
||||
return ts;
|
||||
}
|
||||
|
||||
/* What a pain in the ass. */
|
||||
struct tm *get_gmtoff(long *tz) {
|
||||
time_t tt;
|
||||
struct tm *t;
|
||||
|
||||
tt = time(NULL);
|
||||
t = localtime(&tt);
|
||||
#ifdef BSD
|
||||
*tz = t->tm_gmtoff;
|
||||
#else
|
||||
*tz = - timezone;
|
||||
if(t->tm_isdst)
|
||||
*tz += 3600;
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
/* What another pain in the ass. */
|
||||
|
||||
static char *months[] = {
|
||||
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
||||
};
|
||||
|
||||
static int ydays[] = {
|
||||
0,31,59,90,120,151,181,212,243,273,304,334
|
||||
};
|
||||
|
||||
int find_month(char *mon) {
|
||||
register int x;
|
||||
|
||||
for(x=0;x<12;x++)
|
||||
if(!strcmp(months[x],mon))
|
||||
return x;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define find_yday(mon,day) (ydays[mon] + day)
|
||||
|
||||
int later_than(char *last_modified, char *ims) {
|
||||
char idate[MAX_STRING_LEN], ldate[MAX_STRING_LEN];
|
||||
char itime[MAX_STRING_LEN], ltime[MAX_STRING_LEN];
|
||||
char w[MAX_STRING_LEN];
|
||||
int lday,lmon,lyear, iday,imon,iyear, lhour,lmin, ihour,imin, x;
|
||||
long lsec, isec;
|
||||
|
||||
sscanf(ims,"%*s %s %s",idate,itime);
|
||||
sscanf(last_modified,"%*s %s %s",ldate,ltime);
|
||||
|
||||
getword(w,idate,'-');
|
||||
sscanf(w,"%d",&iday);
|
||||
getword(w,ldate,'-');
|
||||
sscanf(w,"%d",&lday);
|
||||
|
||||
getword(w,idate,'-');
|
||||
imon = find_month(w);
|
||||
getword(w,ldate,'-');
|
||||
lmon = find_month(w);
|
||||
|
||||
sscanf(idate,"%d",&iyear);
|
||||
sscanf(ldate,"%d",&lyear);
|
||||
|
||||
x = lyear - iyear;
|
||||
if(x > 0) return 0;
|
||||
if(x < 0) return 1;
|
||||
|
||||
x = find_yday(lmon, lday) - find_yday(imon,iday);
|
||||
if(x > 0) return 0;
|
||||
if(x < 0) return 1;
|
||||
|
||||
sscanf(itime,"%d:%d:%ld",&ihour,&imin,&isec);
|
||||
sscanf(ltime,"%d:%d:%ld",&lhour,&lmin,&lsec);
|
||||
|
||||
isec += (imin*60) + (ihour*3600);
|
||||
lsec += (lmin*60) + (lhour*3600);
|
||||
|
||||
x = lsec - isec;
|
||||
if(x > 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Match = 0, NoMatch = 1, Abort = -1 */
|
||||
/* Based loosely on sections of wildmat.c by Rich Salz */
|
||||
int strcmp_match(char *str, char *exp) {
|
||||
int x,y;
|
||||
|
||||
for(x=0,y=0;exp[y];++y,++x) {
|
||||
if((!str[x]) && (exp[y] != '*'))
|
||||
return -1;
|
||||
if(exp[y] == '*') {
|
||||
while(exp[++y] == '*');
|
||||
if(!exp[y])
|
||||
return 0;
|
||||
while(str[x]) {
|
||||
int ret;
|
||||
if((ret = strcmp_match(&str[x++],&exp[y])) != 1)
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
} else
|
||||
if((exp[y] != '?') && (str[x] != exp[y]))
|
||||
return 1;
|
||||
}
|
||||
return (str[x] != '\0');
|
||||
}
|
||||
|
||||
int is_matchexp(char *str) {
|
||||
register int x;
|
||||
|
||||
for(x=0;str[x];x++)
|
||||
if((str[x] == '*') || (str[x] == '?'))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strsubfirst(int start,char *dest, char *src)
|
||||
{
|
||||
char tmp[MAX_STRING_LEN];
|
||||
@ -69,6 +193,15 @@ void getparents(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
void no2slash(char *name) {
|
||||
register int x,y;
|
||||
|
||||
for(x=0; name[x]; x++)
|
||||
if(x && (name[x-1] == '/') && (name[x] == '/'))
|
||||
for(y=x+1;name[y-1];y++)
|
||||
name[y-1] = name[y];
|
||||
}
|
||||
|
||||
void make_dirstr(char *s, int n, char *d) {
|
||||
register int x,f;
|
||||
|
||||
@ -101,6 +234,23 @@ void strcpy_dir(char *d, char *s) {
|
||||
d[x] = '\0';
|
||||
}
|
||||
|
||||
void chdir_file(char *file) {
|
||||
int i;
|
||||
|
||||
if((i = rind(file,'/')) == -1)
|
||||
return;
|
||||
file[i] = '\0';
|
||||
chdir(file);
|
||||
file[i] = '/';
|
||||
}
|
||||
|
||||
void http2cgi(char *w) {
|
||||
register int x;
|
||||
|
||||
for(x=strlen(w);x != -1; --x)
|
||||
w[x+5]= (w[x] == '-' ? '_' : toupper(w[x]));
|
||||
strncpy(w,"HTTP_",5);
|
||||
}
|
||||
|
||||
void getline_timed_out() {
|
||||
char errstr[MAX_STRING_LEN];
|
||||
@ -113,12 +263,15 @@ void getline_timed_out() {
|
||||
}
|
||||
|
||||
int getline(char *s, int n, int f, unsigned int timeout) {
|
||||
register int i=0;
|
||||
register int i=0, ret;
|
||||
|
||||
signal(SIGALRM,getline_timed_out);
|
||||
alarm(timeout);
|
||||
while(1) {
|
||||
if(read(f,&s[i],1) <= 0) {
|
||||
if((ret = read(f,&s[i],1)) <= 0) {
|
||||
/* Mmmmm, Solaris. */
|
||||
if((ret == -1) && (errno == EINTR))
|
||||
continue;
|
||||
s[i] = '\0';
|
||||
return 1;
|
||||
}
|
||||
@ -311,6 +464,34 @@ char *make_env_str(char *name, char *value, FILE *out) {
|
||||
return t;
|
||||
}
|
||||
|
||||
char **new_env(char **env, int to_add, int *pos) {
|
||||
if(!env) {
|
||||
*pos = 0;
|
||||
return (char **)malloc((to_add+1)*sizeof(char *));
|
||||
}
|
||||
else {
|
||||
int x;
|
||||
char **newenv;
|
||||
|
||||
for(x=0;env[x];x++);
|
||||
if(!(newenv = (char **)malloc((to_add+x+1)*(sizeof(char *)))))
|
||||
return NULL;
|
||||
for(x=0;env[x];x++)
|
||||
newenv[x] = env[x];
|
||||
*pos = x;
|
||||
free(env);
|
||||
return newenv;
|
||||
}
|
||||
}
|
||||
|
||||
void free_env(char **env) {
|
||||
int x;
|
||||
|
||||
for(x=0;env[x];x++)
|
||||
free(env[x]);
|
||||
free(env);
|
||||
}
|
||||
|
||||
int can_exec(struct stat *finfo) {
|
||||
if(user_id == finfo->st_uid)
|
||||
if(finfo->st_mode & S_IXUSR)
|
||||
@ -453,8 +634,20 @@ int get_portnum(int sd,FILE *out) {
|
||||
len = sizeof(struct sockaddr);
|
||||
if(getsockname(sd,&addr,&len) < 0)
|
||||
die(SERVER_ERROR,"could not get port number",out);
|
||||
return ntohs(((struct sockaddr_in *)&addr)->sin_port);
|
||||
}
|
||||
|
||||
return(((struct sockaddr_in *)&addr)->sin_port);
|
||||
char *find_fqdn(struct hostent *p) {
|
||||
int x;
|
||||
|
||||
if(ind(p->h_name,'.') == -1) {
|
||||
for(x=0;p->h_aliases[x];++x) {
|
||||
if((ind(p->h_aliases[x],'.') != -1) &&
|
||||
(!strncmp(p->h_aliases[x],p->h_name,strlen(p->h_name))))
|
||||
return strdup(p->h_aliases[x]);
|
||||
}
|
||||
return NULL;
|
||||
} else return strdup(p->h_name);
|
||||
}
|
||||
|
||||
void get_remote_host(int fd) {
|
||||
@ -462,9 +655,9 @@ void get_remote_host(int fd) {
|
||||
int len;
|
||||
struct in_addr *iaddr;
|
||||
struct hostent *hptr;
|
||||
|
||||
|
||||
len = sizeof(struct sockaddr);
|
||||
|
||||
|
||||
if ((getpeername(fd, &addr, &len)) < 0) {
|
||||
remote_host=NULL;
|
||||
remote_ip=NULL;
|
||||
@ -479,7 +672,21 @@ void get_remote_host(int fd) {
|
||||
remote_name = remote_host;
|
||||
}
|
||||
else remote_host = NULL;
|
||||
|
||||
|
||||
/* Grrr. Check THAT name to make sure it's really the name of the addr. */
|
||||
/* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
|
||||
if(remote_host) {
|
||||
char **haddr;
|
||||
hptr = gethostbyname(remote_host);
|
||||
if (hptr) {
|
||||
for(haddr=hptr->h_addr_list;*haddr;haddr++) {
|
||||
if(((struct in_addr *)(*haddr))->s_addr == iaddr->s_addr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if((!hptr) || (!(*haddr)))
|
||||
remote_host = NULL;
|
||||
}
|
||||
remote_ip = inet_ntoa(*iaddr);
|
||||
if(!remote_host)
|
||||
remote_name = remote_ip;
|
||||
@ -489,8 +696,7 @@ char *get_remote_logname(FILE *fd) {
|
||||
int len;
|
||||
char *result;
|
||||
#ifdef NEXT
|
||||
struct sockaddr_in sa_server;
|
||||
struct sockaddr sa_client;
|
||||
struct sockaddr sa_server, sa_client;
|
||||
#else
|
||||
struct sockaddr_in sa_server,sa_client;
|
||||
#endif
|
||||
@ -515,9 +721,7 @@ void get_local_host()
|
||||
if(!server_hostname) {
|
||||
struct hostent *p;
|
||||
gethostname(str, len);
|
||||
if(p=gethostbyname(str))
|
||||
server_hostname = strdup(p->h_name);
|
||||
else {
|
||||
if((!(p=gethostbyname(str))) || (!(server_hostname = find_fqdn(p)))) {
|
||||
fprintf(stderr,"httpd: cannot determine local host name.\n");
|
||||
fprintf(stderr,"Use ServerName to set it manually.\n");
|
||||
exit(1);
|
||||
|
@ -7,6 +7,8 @@ CC= gcc
|
||||
#CFLAGS= -O2
|
||||
#For debugging
|
||||
CFLAGS= -g
|
||||
# For SCO ODT
|
||||
#EXTRA_LIBS= -lcrypt_i
|
||||
|
||||
RM= /bin/rm -f
|
||||
#--- You shouldn't have to edit anything else. ---
|
||||
@ -14,7 +16,7 @@ RM= /bin/rm -f
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
all: htpasswd unescape
|
||||
all: htpasswd unescape inc2shtml
|
||||
|
||||
ibm: $(OBJS)
|
||||
make all CC=gcc
|
||||
@ -38,11 +40,14 @@ tar: htpasswd unescape
|
||||
$(RM) htpasswd unescape
|
||||
|
||||
htpasswd: htpasswd.c
|
||||
$(CC) $(CFLAGS) htpasswd.c -o htpasswd
|
||||
$(CC) $(CFLAGS) htpasswd.c -o htpasswd $(EXTRA_LIBS)
|
||||
|
||||
unescape: unescape.c
|
||||
$(CC) $(CFLAGS) unescape.c -o unescape
|
||||
|
||||
inc2shtml: inc2shtml.c
|
||||
$(CC) $(CFLAGS) inc2shtml.c -o inc2shtml
|
||||
|
||||
clean:
|
||||
rm -f htpasswd
|
||||
rm -f htpasswd unescape inc2shtml
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
102
support/inc2shtml.c
Normal file
102
support/inc2shtml.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* inc2shtml: Convert httpd <1.1 style includes to 1.2 style
|
||||
*
|
||||
* Rob McCool
|
||||
*
|
||||
* Usage: inc2shtml [filename]
|
||||
*
|
||||
* If filename is given, this program will open filename. If not, it will
|
||||
* look on stdin. It will output the new shtml file on stdout.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_STRING_LEN 256
|
||||
|
||||
void usage(char *argv0) {
|
||||
fprintf(stderr,"Usage: %s [filename]\n",argv0);
|
||||
fprintf(stderr,"If filename is given, this program will open filename.\n");
|
||||
fprintf(stderr,"If not, it will look on stdin for the inc file.\n");
|
||||
fprintf(stderr,
|
||||
"In either case, it will write the new shtml file on stdout.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void translate_tag(char *tag, FILE *fd) {
|
||||
char *tp = tag, *tp2;
|
||||
int url;
|
||||
|
||||
url = (*tp == 'U' || *tp == 'u' ? 1 : 0);
|
||||
|
||||
while(*tp++ != '\"');
|
||||
tp2 = tp + 1;
|
||||
while(*tp2 != '\"') ++tp2;
|
||||
*tp2 = '\0';
|
||||
if(*tp == '|') {
|
||||
fprintf(fd,"<!--#exec cmd=\"%s",++tp);
|
||||
if(url) fputs(" '$QUERY_STRING_UNESCAPED'",fd);
|
||||
fputs("\"-->",fd);
|
||||
} else
|
||||
fprintf(fd,"<!--#include virtual=\"%s\"-->",tp);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[]) {
|
||||
FILE *f;
|
||||
int c,x,p;
|
||||
char c2;
|
||||
char *lookfor = "<inc srv";
|
||||
|
||||
switch(argc) {
|
||||
case 1:
|
||||
f = stdin;
|
||||
break;
|
||||
case 2:
|
||||
if(!(f = fopen(argv[1],"r"))) {
|
||||
perror("fopen");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
p=0;
|
||||
while(1) {
|
||||
c = fgetc(f);
|
||||
if(c == -1) {
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
c2 = (char)c;
|
||||
if(isalpha((char)c))
|
||||
c = tolower((char)c);
|
||||
if(c == lookfor[p]) {
|
||||
if(!lookfor[++p]) {
|
||||
char tag[MAX_STRING_LEN];
|
||||
|
||||
x=0;
|
||||
c = fgetc(f); /* get space */
|
||||
while(c != '>') {
|
||||
tag[x++] = c;
|
||||
c = fgetc(f);
|
||||
if(c == -1) {
|
||||
fputs("<inc srv ",stdout);
|
||||
fputs(tag,stdout);
|
||||
fflush(stdout);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
tag[x] = '\0';
|
||||
translate_tag(tag,stdout);
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(x=0;x<p;x++)
|
||||
fputc(lookfor[x],stdout);
|
||||
fputc(c2,stdout);
|
||||
p=0;
|
||||
}
|
||||
}
|
||||
}
|
BIN
support/unescape
BIN
support/unescape
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user