Add nuttx to the system framework, which is 10.1.0

This commit is contained in:
TangYiwen123
2021-06-09 14:33:15 +08:00
parent 06c351e27c
commit 804bd57aa0
5000 changed files with 1488544 additions and 0 deletions
@@ -0,0 +1,134 @@
############################################################################
# apps/netutils/cgi-src/Makefile
#
# Copyright (C) 2009, 2011-2012 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
include $(APPDIR)/Make.defs
CFLAGS += ${shell $(INCDIR) "$(CC)" "$(APPDIR)$(DELIM)netutils$(DELIM)thttpd"}
CGIBINDIR = $(APPDIR)/netutils/thttpd/cgi-bin
CLEANFILES = *.o redirect ssi phf
BIN1 = phf
BIN2 = redirect
BIN3 = ssi
BIN = $(BIN1) $(BIN2) $(BIN3)
R1SRCS1 = $(BIN1).c
R1OBJS1 = $(R1SRCS1:.c=.o)
R2SRC1 = $(BIN1)-thunk.S
R2OBJ1 = $(R2SRC1:.S=.o)
R1SRCS2 = $(BIN2).c
R1OBJS2 = $(R1SRCS2:.c=.o)
R2SRC2 = $(BIN2)-thunk.S
R2OBJ2 = $(R2SRC2:.S=.o)
R1SRCS3 = $(BIN3).c
R1OBJS3 = $(R1SRCS3:.c=.o)
R2SRC3 = $(BIN3)-thunk.S
R2OBJ3 = $(R2SRC3:.S=.o)
DERIVED = $(R2SRC1) $(R2SRC2) $(R2SRC3)
R1COBJS = $(R1OBJS1) $(R1OBJS2) $(R1OBJS3)
R2AOBJS = $(R2OBJ1) $(R2OBJ2) $(R2OBJ3)
all: $(BIN1) $(BIN2) $(BIN3)
$(R1COBJS): %.o: %.c
@echo "CC: $<"
$(CC) -c $(CPICFLAGS) $< -o $@
$(R2AOBJS): %.o: %.S
@echo "AS: $<"
@$(CC) -c $(CPICFLAGS) $< -o $@
# BIN1
$(BIN1).r1: $(R1OBJS1)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS1) -o $@ $^
$(R2SRC1): $(BIN1).r1
@echo "MK: $<"
@$(MKNXFLAT) -o $@ $^
$(BIN1).r2: $(R2OBJ1)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS2) -o $@ $(R1OBJS1) $(R2OBJ1)
$(BIN1): $(BIN1).r2
@echo "LD: $<"
@$(LDNXFLAT) $(LDNXFLATFLAGS) -o $@ $^
#BIN2
$(BIN2).r1: $(R1OBJS2)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS1) -o $@ $^
$(R2SRC2): $(BIN2).r1
@echo "MK: $<"
@$(MKNXFLAT) -o $@ $^
$(BIN2).r2: $(R2OBJ2)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS2) -o $@ $(R1OBJS2) $(R2OBJ2)
$(BIN2): $(BIN2).r2
@echo "LD: $<"
@$(LDNXFLAT) $(LDNXFLATFLAGS) -o $@ $^
# BIN3
$(BIN3).r1: $(R1OBJS3)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS1) -o $@ $^
$(R2SRC3): $(BIN3).r1
@echo "MK: $<"
@$(MKNXFLAT) -o $@ $^
$(BIN3).r2: $(R2OBJ3)
@echo "LD: $<"
@$(LD) $(NXFLATLDFLAGS2) -o $@ $(R1OBJS3) $(R2OBJ3)
$(BIN3): $(BIN3).r2
@echo "LD: $<"
@$(LDNXFLAT) $(LDNXFLATFLAGS) -o $@ $^
clean:
@rm -f $(BIN1) $(BIN2) $(BIN3) *.r1 *.r2 *-thunk.S *~ .*.swp
$(call CLEAN)
distclean: clean
@@ -0,0 +1,81 @@
/****************************************************************************
* netutils/thttpd/cgi-src/phf.c
* Cracker trap
*
* Copyright (C) 2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derived from the file of the same name in the original THTTPD package:
*
* Copyright © 1996 by Jef Poskanzer <jef@mail.acme.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
/* Old distributions of the NCSA and Apache web servers included a
* version of the phf program that had a bug. The program could
* easily be made to run arbitrary shell commands. There is no real
* legitimate use for phf, so any attempts to run it must be considered
* to be attacks. Accordingly, this version of phf logs the attack
* on stderr and then returns a page on CONFIG_THTTPD_CGI_OUTFD indicating
* that phf doesn't exist.
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_THTTPD_BINFS
int phf_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
fprintf(stderr, "phf CGI probe from %s\n", getenv("REMOTE_ADDR"));
printf("\
Content-type: text/html\n\
Status: 404/html\n\
\n\
<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n\
<BODY><H2>404 Not Found</H2>\n\
The requested object does not exist on this server.\n\
The link you followed is either outdated, inaccurate,\n\
or the server has been instructed not to let you have it.\n\
</BODY></HTML>\n");
return 0;
}
@@ -0,0 +1,274 @@
/****************************************************************************
* netutils/thttpd/cgi-src/redirect.c
* Simple redirection CGI program
*
* Copyright (C) 2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derived from the file of the same name in the original THTTPD package:
*
* Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
/* Three steps to set up a redirection:
*
* 1. Make sure your web server is set up to allow CGI programs.
* 2. Make a symbolic link from the file you want to redirect,
* pointing at this program in the CGI bin directory.
* 3. Add an entry to the file ".redirects" in the directory where your
* http server runs CGI programs. For most servers, this is the
* directory where the given CGI program lives. The format of the
* file is a bunch of lines with a filename, whitespace, and the new
* URL. For example:
*
* /test/oldfile.html http://www.acme.com/test/newfile.html
*
* The easiest way to figure out precisely what filename to put into
* .redirects is to set up the symlink and then click on it. You'll get
* back a "404 Not Found" page which includes the filename as received by
* the redirect program, and that's what you want to use.
*
* Note: this is designed for thttpd (http://www.acme.com/software/thttpd/)
* and using it with other web servers may require some hacking. A possible
* gotcha is with the symbolic link from the old file pointing at this
* script - servers other than thttpd may not allow that link to be run
* as a CGI program, because they don't check the link to see that it
* points into the allowed CGI directory.
*
* Note two: It would be really cool to have this program look for
* the .redirects file in the same directory as the file being redirected,
* instead of in the binaries directory. Unfortunately, this appears
* to be impossible with the information CGI gives, plus the non-standardized
* but widespread practice of running CGI programs in the directory where
* the binary lives. Perhaps CGI 1.2 will address this.
*/
/****************************************************************************
* Public Functions
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "config.h"
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
#define LINE_SIZE 80
/****************************************************************************
* Private Data
****************************************************************************/
static char g_iobuffer[LINE_SIZE];
static char g_file[LINE_SIZE];
static char g_url[LINE_SIZE];
/****************************************************************************
* Private Functions
****************************************************************************/
static void internal_error(char *reason)
{
char *title = "500 Internal Error";
printf("\
Status: %s\n\
Content-type: text/html\n\
\n\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
Something unusual went wrong during a redirection request:\n\
<BLOCKQUOTE>\n\
%s\n\
</BLOCKQUOTE>\n\
</BODY></HTML>\n", title, title, title, reason);
}
static void not_found(char *script_name)
{
char *title = "404 Not Found";
printf("\
Status: %s\n\
Content-type: text/html\n\
\n\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
The requested filename, %s, is set up to be redirected to another URL;\n\
however, the new URL has not yet been specified.\n\
</BODY></HTML>\n", title, title, title, script_name);
}
static void moved(char *script_name, char *url)
{
char *title = "Moved";
printf("\
Location: %s\n\
Content-type: text/html\n\
\n\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
The requested filename, %s, has moved to a new URL:\n\
<A HREF=\"%s\">%s</A>.\n\
</BODY></HTML>\n", url, title, title, script_name, url, url);
}
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_THTTPD_BINFS
int redirect_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
char *script_name;
char *path_info;
char *cp = 0;
FILE *fp;
char *star;
int errcode = 0;
/* Get the name that we were run as, which is the filename being **
* redirected.
*/
script_name = getenv("SCRIPT_NAME");
if (!script_name)
{
internal_error("Couldn't get SCRIPT_NAME environment variable.");
return 1;
}
/* Append the PATH_INFO, if any. This allows redirection of whole **
* directories.
*/
path_info = getenv("PATH_INFO");
if (path_info)
{
cp = (char *)malloc(strlen(script_name) + strlen(path_info) + 1);
if (!cp)
{
internal_error("Out of memory.");
return 2;
}
sprintf(cp, "%s%s", script_name, path_info);
script_name = cp;
}
/* Open the redirects file. */
fp = fopen(".redirects", "r");
if (fp == (FILE *) 0)
{
internal_error("Couldn't open .redirects file.");
errcode = 3;
goto errout_with_cp;
}
/* Search the file for a matching entry. */
while (fgets(g_iobuffer, LINE_SIZE, fp) != NULL)
{
/* Remove comments. */
cp = strchr(g_iobuffer, '#');
if (cp)
{
*cp = '\0';
}
/* Skip leading whitespace. */
cp = g_iobuffer;
cp += strspn(cp, " \t");
/* Check for blank line. */
if (*cp != '\0')
{
/* Parse line. */
if (sscanf(cp, "%[^ \t\n] %[^ \t\n]", g_file, g_url) == 2)
{
/* Check for wildcard match. */
star = strchr(g_file, '*');
if (star != (char *)0)
{
/* Check for leading match. */
if (strncmp(g_file, script_name, star - g_file) == 0)
{
/* Got it; put together the full name. */
strcat(g_url, script_name + (star - g_file));
/* XXX Whack the script_name, too? */
moved(script_name, g_url);
goto success_out;
}
}
/* Check for exact match. */
if (strcmp(g_file, script_name) == 0)
{
/* Got it. */
moved(script_name, g_url);
goto success_out;
}
}
}
}
/* No match found. */
not_found(script_name);
errcode = 4;
success_out:
fclose(fp);
errout_with_cp:
if (cp)
{
free(cp);
}
return errcode;
}
@@ -0,0 +1,963 @@
/****************************************************************************
* netutils/thttpd/cgi-src/ssi.c
* Server-side-includes CGI program
*
* Copyright (C) 2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derived from the file of the same name in the original THTTPD package:
*
* Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <nuttx/lib/regex.h>
#include "config.h"
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
#define ST_GROUND 0
#define ST_LESSTHAN 1
#define ST_BANG 2
#define ST_MINUS1 3
#define ST_MINUS2 4
#define SF_BYTES 0
#define SF_ABBREV 1
#define DI_CONFIG 0
#define DI_INCLUDE 1
#define DI_ECHO 2
#define DI_FSIZE 3
#define DI_FLASTMOD 4
#define BUFFER_SIZE 512
#define TIMEFMT_SIZE 80
#define MAX_TAGS 32
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void read_file(FILE *instream, char *vfilename, char *filename);
/****************************************************************************
* Private Data
****************************************************************************/
static char *g_url;
static char g_timeformat[TIMEFMT_SIZE];
static char g_iobuffer1[BUFFER_SIZE];
static char g_iobuffer2[BUFFER_SIZE];
static char *g_tags[MAX_TAGS];
static int g_sizefmt;
static struct stat g_sb;
/****************************************************************************
* Private Functions
****************************************************************************/
static void internal_error(char *reason)
{
char *title = "500 Internal Error";
printf("\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
Something unusual went wrong during a server-side-includes request:\n\
<BLOCKQUOTE>\n\
%s\n\
</BLOCKQUOTE>\n\
</BODY></HTML>\n", title, title, reason);
}
static void not_found(char *filename)
{
char *title = "404 Not Found";
printf("\
<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
<BODY><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
does not seem to exist.\n\
</BODY></HTML>\n", title, title, filename);
}
static void not_found2(char *directive, char *tag, char *filename)
{
char *title = "Not Found";
printf("\
<HR><H2>%s</H2>\n\
The filename requested in a %s %s directive, %s,\n\
does not seem to exist.\n\
<HR>\n", title, directive, tag, filename);
}
static void not_permitted(char *directive, char *tag, char *val)
{
char *title = "Not Permitted";
printf("\
<HR><H2>%s</H2>\n\
The filename requested in the %s %s=%s directive\n\
may not be fetched.\n\
<HR>\n", title, directive, tag, val);
}
static void unknown_directive(char *filename, char *directive)
{
char *title = "Unknown Directive";
printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use an unknown directive, %s.\n\
<HR>\n", title, filename, directive);
}
static void unknown_tag(char *filename, char *directive, char *tag)
{
char *title = "Unknown Tag";
printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use the directive %s with an unknown tag, %s.\n\
<HR>\n", title, filename, directive, tag);
}
static void unknown_value(char *filename, char *directive, char *tag, char *val)
{
char *title = "Unknown Value";
printf("\
<HR><H2>%s</H2>\n\
The requested server-side-includes filename, %s,\n\
tried to use the directive %s %s with an unknown value, %s.\n\
<HR>\n", title, filename, directive, tag, val);
}
static int get_filename(char *vfilename, char *filename,
char *directive, char *tag, char *val, char *fn,
int fnsize)
{
char *cp;
int vl;
int fl;
/* Used for the various commands that accept a file name. These commands
* accept two tags: virtual Gives a virtual path to a document on the
* server. file Gives a pathname relative to the current directory. ../
* cannot be used in this pathname, nor can absolute paths be used.
*/
vl = strlen(vfilename);
fl = strlen(filename);
if (strcmp(tag, "virtual") == 0)
{
if (strstr(val, "../") != (char *)0)
{
not_permitted(directive, tag, val);
return -1;
}
/* Figure out root using difference between vfilename and filename. */
if (vl > fl || strcmp(vfilename, &filename[fl - vl]) != 0)
{
return -1;
}
if (fl - vl + strlen(val) >= fnsize)
{
return -1;
}
strncpy(fn, filename, fl - vl);
strcpy(&fn[fl - vl], val);
}
else if (strcmp(tag, "file") == 0)
{
if (val[0] == '/' || strstr(val, "../") != (char *)0)
{
not_permitted(directive, tag, val);
return -1;
}
if (fl + 1 + strlen(val) >= fnsize)
{
return -1;
}
strcpy(fn, filename);
cp = strrchr(fn, '/');
if (cp == (char *)0)
{
cp = &fn[strlen(fn)];
*cp = '/';
}
strcpy(++cp, val);
}
else
{
unknown_tag(filename, directive, tag);
return -1;
}
return 0;
}
static int check_filename(char *filename)
{
static int inited = 0;
static char *cgi_pattern;
#ifdef CONFIG_AUTH_FILE
struct stat sb;
char *dirname;
char *authname;
char *cp;
int fnl;
int r;
#endif
if (!inited)
{
/* Get the cgi pattern. */
cgi_pattern = getenv("CGI_PATTERN");
#ifdef CGI_PATTERN
if (cgi_pattern == (char *)0)
{
cgi_pattern = CGI_PATTERN;
}
#endif /* CGI_PATTERN */
inited = 1;
}
/* ../ is not permitted. */
if (strstr(filename, "../") !=NULL)
{
return 0;
}
/* Ensure that we are not reading a basic auth password file. */
#ifdef CONFIG_AUTH_FILE
fnl = strlen(filename);
if (strcmp(filename, CONFIG_AUTH_FILE) == 0 ||
(fnl >= sizeof(CONFIG_AUTH_FILE) &&
strcmp(&filename[fnl - sizeof(CONFIG_AUTH_FILE) + 1], CONFIG_AUTH_FILE) == 0 &&
filename[fnl - sizeof(CONFIG_AUTH_FILE)] == '/'))
{
return 0;
}
/* Check for an auth file in the same directory. We can't do an actual **
* auth password check here because CGI programs are not given the **
* authorization header, for security reasons. So instead we just **
* prohibit access to all auth-protected files.
*/
dirname = strdup(filename);
if (dirname == (char *)0)
{
/* out of memory */
return 0;
}
cp = strrchr(dirname, '/');
if (cp == (char *)0)
{
strcpy(dirname, ".");
}
else
{
*cp = '\0';
}
authname = malloc(strlen(dirname) + 1 + sizeof(CONFIG_AUTH_FILE));
if (!authname)
{
/* out of memory */
free(dirname);
return 0;
}
sprintf(authname, "%s/%s", dirname, CONFIG_AUTH_FILE);
r = stat(authname, &sb);
free(dirname);
free(authname);
if (r == 0)
{
return 0;
}
#endif /* CONFIG_AUTH_FILE */
/* Ensure that we are not reading a CGI file. */
if (cgi_pattern != (char *)0 && match(cgi_pattern, filename))
{
return 0;
}
return 1;
}
static void show_time(time_t t, int gmt)
{
struct tm *tmP;
if (gmt)
{
tmP = gmtime(&t);
}
else
{
tmP = localtime(&t);
}
if (strftime(g_iobuffer2, BUFFER_SIZE, g_timeformat, tmP) > 0)
{
puts(g_iobuffer2);
}
}
static void show_size(off_t size)
{
switch (g_sizefmt)
{
case SF_BYTES:
printf("%ld", (long)size); /* spec says should have commas */
break;
case SF_ABBREV:
if (size < 1024)
{
printf("%ld", (long)size);
}
else if (size < 1024 * 1024)
{
printf("%ldK", (long)size / 1024L);
}
else if (size < 1024 * 1024 * 1024)
{
printf("%ldM", (long)size / (1024L * 1024L));
}
else
{
printf("%ldG", (long)size / (1024L * 1024L * 1024L));
}
break;
}
}
static void do_config(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
/* The config directive controls various aspects of the file parsing. **
* There are two valid tags: g_timeformat Gives the server a new format to
* use when providing dates. This is a string compatible with the
* strftime library call. g_sizefmt Determines the formatting to be used
* when displaying the size of a file. Valid choices are bytes, for a
* formatted byte count (formatted as 1,234,567), or abbrev for an
* abbreviated version displaying the number of kilobytes or megabytes the
* file occupies.
*/
if (strcmp(tag, "g_timeformat") == 0)
{
strncpy(g_timeformat, val, TIMEFMT_SIZE - 1);
g_timeformat[TIMEFMT_SIZE - 1] = '\0';
}
else if (strcmp(tag, "g_sizefmt") == 0)
{
if (strcmp(val, "bytes") == 0)
{
g_sizefmt = SF_BYTES;
}
else if (strcmp(val, "abbrev") == 0)
{
g_sizefmt = SF_ABBREV;
}
else
{
unknown_value(filename, directive, tag, val);
}
}
else
{
unknown_tag(filename, directive, tag);
}
}
static void do_include(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
FILE *instream2;
int ret;
/* Inserts the text of another document into the parsed document. */
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
}
if (!check_filename(g_iobuffer1))
{
not_permitted(directive, tag, g_iobuffer1);
return;
}
instream2 = fopen(g_iobuffer1, "r");
if (instream2 == (FILE *) 0)
{
not_found2(directive, tag, g_iobuffer1);
return;
}
if (strcmp(tag, "virtual") == 0)
{
if (strlen(val) <BUFFER_SIZE)
{
strcpy(g_iobuffer2, val);
}
else
{
strcpy(g_iobuffer2, g_iobuffer1); /* same size, has to fit */
}
}
else
{
if (strlen(vfilename) + 1 + strlen(val) < BUFFER_SIZE)
{
char *cp;
strcpy(g_iobuffer2, vfilename);
cp = strrchr(g_iobuffer2, '/');
if (cp == (char *)0)
{
cp = &g_iobuffer2[strlen(g_iobuffer2)];
*cp = '/';
}
strcpy(++cp, val);
}
else
{
strcpy(g_iobuffer2, g_iobuffer1); /* same size, has to fit */
}
}
read_file(instream2, g_iobuffer2, g_iobuffer1);
fclose(instream2);
}
static void do_echo(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
char *cp;
/* Prints the value of one of the include variables. Any dates are
* printed subject to the currently configured g_timeformat. The only valid
* tag is var, whose value is the name of the variable you wish to echo.
*/
if (strcmp(tag, "var") != 0)
{
unknown_tag(filename, directive, tag);
}
else
{
if (strcmp(val, "DOCUMENT_NAME") == 0)
{
/* The current filename. */
puts(filename);
}
else if (strcmp(val, "DOCUMENT_URI") == 0)
{
/* The virtual path to this file (such as /~robm/foo.shtml). */
puts(vfilename);
}
else if (strcmp(val, "QUERY_STRING_UNESCAPED") == 0)
{
/* The unescaped version of any search query the client sent. */
cp = getenv("QUERY_STRING");
if (cp != (char *)0)
{
puts(cp);
}
}
else if (strcmp(val, "DATE_LOCAL") == 0)
{
struct timeval tm;
/* The current date, local time zone. */
gettimeofday(&tm, NULL);
show_time(tm.tv_sec, 0);
}
else if (strcmp(val, "DATE_GMT") == 0)
{
struct timeval tm;
/* Same as DATE_LOCAL but in Greenwich mean time. */
gettimeofday(&tm, NULL);
show_time(tm.tv_sec, 1);
}
#if 0 /* fstat is not yet supported */
else if (strcmp(val, "LAST_MODIFIED") == 0)
{
/* The last modification date of the current document. */
if (fstat(fileno(instream), &g_sb) >= 0)
{
show_time(g_sb.st_mtime, 0);
}
}
#endif
else
{
/* Try an environment variable. */
cp = getenv(val);
if (cp == (char *)0)
{
unknown_value(filename, directive, tag, val);
}
else
{
puts(cp);
}
}
}
}
static void do_fsize(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
int ret;
/* Prints the size of the specified file. */
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
}
if (stat(g_iobuffer1, &g_sb) < 0)
{
not_found2(directive, tag, g_iobuffer1);
return;
}
show_size(g_sb.st_size);
}
static void do_flastmod(FILE *instream, char *vfilename, char *filename,
char *directive, char *tag, char *val)
{
int ret;
/* Prints the last modification date of the specified file. */
ret = get_filename(vfilename, filename, directive, tag, val, g_iobuffer1, BUFFER_SIZE);
if (ret < 0)
{
return;
}
if (stat(g_iobuffer1, &g_sb) < 0)
{
not_found2(directive, tag, g_iobuffer1);
return;
}
show_time(g_sb.st_mtime, 0);
}
static void parse(FILE *instream, char *vfilename, char *filename, char *str)
{
char *directive;
char *cp;
int ntags;
int dirn;
int i;
char *val;
directive = str;
directive += strspn(directive, " \t\n\r");
ntags = 0;
cp = directive;
for (;;)
{
cp = strpbrk(cp, " \t\n\r\"");
if (cp == (char *)0)
{
break;
}
if (*cp == '"')
{
cp = strpbrk(cp + 1, "\"");
cp++;
if (*cp == '\0')
{
break;
}
}
*cp++ = '\0';
cp += strspn(cp, " \t\n\r");
if (*cp == '\0')
{
break;
}
if (ntags < MAX_TAGS)
{
g_tags[ntags++] = cp;
}
}
if (strcmp(directive, "config") == 0)
{
dirn = DI_CONFIG;
}
else if (strcmp(directive, "include") == 0)
{
dirn = DI_INCLUDE;
}
else if (strcmp(directive, "echo") == 0)
{
dirn = DI_ECHO;
}
else if (strcmp(directive, "fsize") == 0)
{
dirn = DI_FSIZE;
}
else if (strcmp(directive, "flastmod") == 0)
{
dirn = DI_FLASTMOD;
}
else
{
unknown_directive(filename, directive);
return;
}
for (i = 0; i < ntags; ++i)
{
if (i > 0)
{
putchar(' ');
}
val = strchr(g_tags[i], '=');
if (val == (char *)0)
{
val = "";
}
else
{
*val++ = '\0';
}
if (*val == '"' && val[strlen(val) - 1] == '"')
{
val[strlen(val) - 1] = '\0';
++val;
}
switch (dirn)
{
case DI_CONFIG:
do_config(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_INCLUDE:
do_include(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_ECHO:
do_echo(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_FSIZE:
do_fsize(instream, vfilename, filename, directive, g_tags[i], val);
break;
case DI_FLASTMOD:
do_flastmod(instream, vfilename, filename, directive, g_tags[i], val);
break;
}
}
}
static void slurp(FILE *instream, char *vfilename, char *filename)
{
int state;
int ich;
int i;
/* Now slurp in the rest of the comment from the input file. */
i = 0;
state = ST_GROUND;
while ((ich = getc(instream)) != EOF)
{
switch (state)
{
case ST_GROUND:
if (ich == '-')
{
state = ST_MINUS1;
}
break;
case ST_MINUS1:
if (ich == '-')
{
state = ST_MINUS2;
}
else
{
state = ST_GROUND;
}
break;
case ST_MINUS2:
if (ich == '>')
{
g_iobuffer1[i - 2] = '\0';
parse(instream, vfilename, filename, g_iobuffer1);
return;
}
else if (ich != '-')
{
state = ST_GROUND;
}
break;
}
if (i < BUFFER_SIZE - 1)
{
g_iobuffer1[i++] = (char)ich;
}
}
}
static void read_file(FILE *instream, char *vfilename, char *filename)
{
int ich;
int state;
/* Copy it to output, while running a state-machine to look for SSI
* directives.
*/
state = ST_GROUND;
while ((ich = getc(instream)) != EOF)
{
switch (state)
{
case ST_GROUND:
if (ich == '<')
{
state = ST_LESSTHAN;
continue;
}
break;
case ST_LESSTHAN:
if (ich == '!')
{
state = ST_BANG;
continue;
}
else
{
state = ST_GROUND;
putchar('<');
}
break;
case ST_BANG:
if (ich == '-')
{
state = ST_MINUS1;
continue;
}
else
{
state = ST_GROUND;
puts("<!");
}
break;
case ST_MINUS1:
if (ich == '-')
{
state = ST_MINUS2;
continue;
}
else
{
state = ST_GROUND;
puts("<!-");
}
break;
case ST_MINUS2:
if (ich == '#')
{
slurp(instream, vfilename, filename);
state = ST_GROUND;
continue;
}
else
{
state = ST_GROUND;
puts("<!--");
}
break;
}
putchar((char)ich);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
#ifdef CONFIG_THTTPD_BINFS
int ssi_main(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
FILE *instream;
char *script_name;
char *path_info;
char *path_translated;
int errcode = 0;
/* Default formats. */
strcpy(g_timeformat, "%a %b %e %T %Z %Y");
g_sizefmt = SF_BYTES;
/* The MIME type has to be text/html. */
puts("Content-type: text/html\n\n");
/* Get the name that we were run as. */
script_name = getenv("SCRIPT_NAME");
if (!script_name)
{
internal_error("Couldn't get SCRIPT_NAME environment variable.");
return 1;
}
/* Append the PATH_INFO, if any, to get the full URL. */
path_info = getenv("PATH_INFO");
if (!path_info)
{
path_info = "";
}
g_url = (char*)malloc(strlen(script_name) + strlen(path_info) + 1);
if (!g_url)
{
internal_error("Out of memory.");
return 2;
}
sprintf(g_url, "%s%s", script_name, path_info);
/* Get the name of the file to parse. */
path_translated = getenv("PATH_TRANSLATED");
if (!path_translated)
{
internal_error("Couldn't get PATH_TRANSLATED environment variable.");
errcode = 3;
goto errout_with_g_url;
}
if (!check_filename(path_translated))
{
not_permitted("initial", "PATH_TRANSLATED", path_translated);
errcode = 4;
goto errout_with_g_url;
}
/* Open it. */
instream = fopen(path_translated, "r");
if (!instream)
{
not_found(path_translated);
errcode = 5;
goto errout_with_g_url;
}
/* Read and handle the file. */
read_file(instream, path_info, path_translated);
fclose(instream);
errout_with_g_url:
free(g_url);
return errcode;
}