mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
lots of CGI work and kepler/lua stuff
git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@95 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
parent
a194849b9e
commit
c511f2986e
@ -53,20 +53,34 @@ config CONFIG_HTTP_TIMEOUT
|
|||||||
help
|
help
|
||||||
Set the timeout of a connection in seconds.
|
Set the timeout of a connection in seconds.
|
||||||
|
|
||||||
|
menu "CGI"
|
||||||
|
|
||||||
config CONFIG_HTTP_HAS_CGI
|
config CONFIG_HTTP_HAS_CGI
|
||||||
bool "Enable CGI"
|
bool "Enable CGI"
|
||||||
default n
|
default n
|
||||||
|
depends on !CONFIG_PLATFORM_WIN32
|
||||||
help
|
help
|
||||||
Enable the CGI capability.
|
Enable the CGI capability. Not available on Win32 platforms.
|
||||||
|
|
||||||
config CONFIG_HTTP_CGI_EXTENSIONS
|
config CONFIG_HTTP_CGI_EXTENSIONS
|
||||||
string "CGI File Extension(s)"
|
string "CGI File Extension(s)"
|
||||||
default ".php,.sh"
|
default ".lua,.lp"
|
||||||
depends on CONFIG_HTTP_HAS_CGI
|
depends on CONFIG_HTTP_HAS_CGI
|
||||||
help
|
help
|
||||||
Tell axhhtpd what file extension(s) are used for CGI.
|
Tell axhhtpd what file extension(s) are used for CGI.
|
||||||
|
|
||||||
This is a comma separated list.
|
This is a comma separated list - e.g. ".php,.pl" etc
|
||||||
|
|
||||||
|
config CONFIG_HTTP_LUA_LAUNCHER
|
||||||
|
string "Lua's CGI Launcher"
|
||||||
|
default "/usr/local/bin/cgi" if CONFIG_PLATFORM_LINUX
|
||||||
|
default "/usr/local/bin/cgi.exe" if CONFIG_PLATFORM_CYGWIN
|
||||||
|
depends on CONFIG_HTTP_HAS_CGI
|
||||||
|
|
||||||
|
help
|
||||||
|
Lua has a special launcher application to run kepler/lua scripts.
|
||||||
|
".lua and .lp" extensions must be defined in CONFIG_HTTP_CGI_EXTENSIONS.
|
||||||
|
endmenu
|
||||||
|
|
||||||
config CONFIG_HTTP_DIRECTORIES
|
config CONFIG_HTTP_DIRECTORIES
|
||||||
bool "Enable Directory Listing"
|
bool "Enable Directory Listing"
|
||||||
|
@ -26,17 +26,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAXREQUESTLENGTH 256
|
#define MAXREQUESTLENGTH 256
|
||||||
#define MAXCGIARGS 100
|
|
||||||
#define BLOCKSIZE 4096
|
#define BLOCKSIZE 4096
|
||||||
|
|
||||||
#define INITIAL_CONNECTION_SLOTS 10
|
#define INITIAL_CONNECTION_SLOTS 10
|
||||||
#define CONFIG_HTTP_DEFAULT_SSL_OPTIONS 0
|
#define CONFIG_HTTP_DEFAULT_SSL_OPTIONS 0
|
||||||
|
|
||||||
#define STATE_WANT_TO_READ_HEAD 1
|
#define STATE_WANT_TO_READ_HEAD 1
|
||||||
#define STATE_WANT_TO_SEND_HEAD 2
|
#define STATE_WANT_TO_SEND_HEAD 2
|
||||||
#define STATE_WANT_TO_READ_FILE 3
|
#define STATE_WANT_TO_READ_FILE 3
|
||||||
#define STATE_WANT_TO_SEND_FILE 4
|
#define STATE_WANT_TO_SEND_FILE 4
|
||||||
#define STATE_DOING_DIR 5
|
#define STATE_DOING_DIR 5
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -67,7 +66,7 @@ struct connstruct
|
|||||||
char actualfile[MAXREQUESTLENGTH];
|
char actualfile[MAXREQUESTLENGTH];
|
||||||
char filereq[MAXREQUESTLENGTH];
|
char filereq[MAXREQUESTLENGTH];
|
||||||
char dirname[MAXREQUESTLENGTH];
|
char dirname[MAXREQUESTLENGTH];
|
||||||
char virtualhostreq[MAXREQUESTLENGTH];
|
char server_name[MAXREQUESTLENGTH];
|
||||||
int numbytes;
|
int numbytes;
|
||||||
char databuf[BLOCKSIZE];
|
char databuf[BLOCKSIZE];
|
||||||
uint8_t is_ssl;
|
uint8_t is_ssl;
|
||||||
@ -75,9 +74,13 @@ struct connstruct
|
|||||||
time_t if_modified_since;
|
time_t if_modified_since;
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
char cgiargs[MAXREQUESTLENGTH];
|
uint8_t is_cgi;
|
||||||
char cgiscriptinfo[MAXREQUESTLENGTH];
|
uint8_t is_lua;
|
||||||
char cgipathinfo[MAXREQUESTLENGTH];
|
int content_length;
|
||||||
|
char remote_addr[MAXREQUESTLENGTH];
|
||||||
|
char uri_request[MAXREQUESTLENGTH];
|
||||||
|
char uri_path_info[MAXREQUESTLENGTH];
|
||||||
|
char uri_query[MAXREQUESTLENGTH];
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
|
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
|
||||||
char authorization[MAXREQUESTLENGTH];
|
char authorization[MAXREQUESTLENGTH];
|
||||||
@ -104,6 +107,8 @@ struct cgiextstruct
|
|||||||
extern struct serverstruct *servers;
|
extern struct serverstruct *servers;
|
||||||
extern struct connstruct *usedconns;
|
extern struct connstruct *usedconns;
|
||||||
extern struct connstruct *freeconns;
|
extern struct connstruct *freeconns;
|
||||||
|
extern const char * const server_version;
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
extern struct cgiextstruct *cgiexts;
|
extern struct cgiextstruct *cgiexts;
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
struct serverstruct *servers;
|
struct serverstruct *servers;
|
||||||
struct connstruct *usedconns;
|
struct connstruct *usedconns;
|
||||||
struct connstruct *freeconns;
|
struct connstruct *freeconns;
|
||||||
|
const char * const server_version = "axhttpd/"AXTLS_VERSION;
|
||||||
|
|
||||||
static void addtoservers(int sd);
|
static void addtoservers(int sd);
|
||||||
static int openlistener(int port);
|
static int openlistener(int port);
|
||||||
@ -162,8 +163,8 @@ int main(int argc, char *argv[])
|
|||||||
addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
|
addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_HTTP_VERBOSE)
|
#if defined(CONFIG_HTTP_VERBOSE)
|
||||||
printf("axhttpd (%s): listening on ports %d (http) and %d (https)\n",
|
printf("%s: listening on ports %d (http) and %d (https)\n",
|
||||||
ssl_version(), CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT);
|
server_version, CONFIG_HTTP_PORT, CONFIG_HTTP_HTTPS_PORT);
|
||||||
TTY_FLUSH();
|
TTY_FLUSH();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -475,15 +476,15 @@ static void addconnection(int sd, char *ip, int is_ssl)
|
|||||||
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
|
#if defined(CONFIG_HTTP_HAS_DIRECTORIES)
|
||||||
tp->dirp = NULL;
|
tp->dirp = NULL;
|
||||||
#endif
|
#endif
|
||||||
*(tp->actualfile) = '\0';
|
*tp->actualfile = '\0';
|
||||||
*(tp->filereq) = '\0';
|
*tp->filereq = '\0';
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
|
||||||
*(tp->cgiargs) = '\0';
|
|
||||||
#endif
|
|
||||||
tp->state = STATE_WANT_TO_READ_HEAD;
|
tp->state = STATE_WANT_TO_READ_HEAD;
|
||||||
tp->reqtype = TYPE_GET;
|
tp->reqtype = TYPE_GET;
|
||||||
tp->close_when_done = 0;
|
tp->close_when_done = 0;
|
||||||
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
|
tp->timeout = time(NULL) + CONFIG_HTTP_TIMEOUT;
|
||||||
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
|
strcpy(tp->remote_addr, ip);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeconnection(struct connstruct *cn)
|
void removeconnection(struct connstruct *cn)
|
||||||
@ -564,3 +565,4 @@ static void ax_chdir(void)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
329
httpd/proc.c
329
httpd/proc.c
@ -38,17 +38,15 @@ static void buildactualfile(struct connstruct *cn);
|
|||||||
static int sanitizefile(const char *buf);
|
static int sanitizefile(const char *buf);
|
||||||
static int sanitizehost(char *buf);
|
static int sanitizehost(char *buf);
|
||||||
static int htaccess_check(struct connstruct *cn);
|
static int htaccess_check(struct connstruct *cn);
|
||||||
|
static const char *getmimetype(const char *name);
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_DIRECTORIES)
|
#if defined(CONFIG_HTTP_DIRECTORIES)
|
||||||
static void urlencode(const uint8_t *s, char *t);
|
static void urlencode(const uint8_t *s, char *t);
|
||||||
static void procdirlisting(struct connstruct *cn);
|
static void procdirlisting(struct connstruct *cn);
|
||||||
static const char *getmimetype(const char *name);
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
static void proccgi(struct connstruct *cn, int has_pathinfo);
|
static void proccgi(struct connstruct *cn);
|
||||||
static int trycgi_withpathinfo(struct connstruct *cn);
|
static void decode_path_info(struct connstruct *cn, char *path_info);
|
||||||
static void split(char *tp, char *sp[], int maxwords, char sc);
|
|
||||||
static int iscgi(const char *fn);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
|
#ifdef CONFIG_HTTP_HAS_AUTHORIZATION
|
||||||
static int auth_check(struct connstruct *cn);
|
static int auth_check(struct connstruct *cn);
|
||||||
@ -58,9 +56,6 @@ static int auth_check(struct connstruct *cn);
|
|||||||
static int procheadelem(struct connstruct *cn, char *buf)
|
static int procheadelem(struct connstruct *cn, char *buf)
|
||||||
{
|
{
|
||||||
char *delim, *value;
|
char *delim, *value;
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
|
||||||
char *cgi_delim;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((delim = strchr(buf, ' ')) == NULL)
|
if ((delim = strchr(buf, ' ')) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -89,13 +84,10 @@ static int procheadelem(struct connstruct *cn, char *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
if ((cgi_delim = strchr(value, '?')))
|
decode_path_info(cn, value);
|
||||||
{
|
#else
|
||||||
*cgi_delim = 0;
|
|
||||||
my_strncpy(cn->cgiargs, cgi_delim+1, MAXREQUESTLENGTH);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
my_strncpy(cn->filereq, value, MAXREQUESTLENGTH);
|
my_strncpy(cn->filereq, value, MAXREQUESTLENGTH);
|
||||||
|
#endif
|
||||||
cn->if_modified_since = -1;
|
cn->if_modified_since = -1;
|
||||||
}
|
}
|
||||||
else if (strcmp(buf, "Host:") == 0)
|
else if (strcmp(buf, "Host:") == 0)
|
||||||
@ -106,7 +98,7 @@ static int procheadelem(struct connstruct *cn, char *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_strncpy(cn->virtualhostreq, value, MAXREQUESTLENGTH);
|
my_strncpy(cn->server_name, value, MAXREQUESTLENGTH);
|
||||||
}
|
}
|
||||||
else if (strcmp(buf, "Connection:") == 0 && strcmp(value, "close") == 0)
|
else if (strcmp(buf, "Connection:") == 0 && strcmp(value, "close") == 0)
|
||||||
{
|
{
|
||||||
@ -128,6 +120,12 @@ static int procheadelem(struct connstruct *cn, char *buf)
|
|||||||
cn->authorization[size] = 0;
|
cn->authorization[size] = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
|
else if (strcmp(buf, "Content-Length:") == 0)
|
||||||
|
{
|
||||||
|
sscanf(value, "%d", &cn->content_length);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -169,7 +167,7 @@ static void procdirlisting(struct connstruct *cn)
|
|||||||
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n"
|
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n"
|
||||||
"<html><body>\n<title>Directory Listing</title>\n"
|
"<html><body>\n<title>Directory Listing</title>\n"
|
||||||
"<h3>Directory listing of %s://%s%s</h3><br />\n",
|
"<h3>Directory listing of %s://%s%s</h3><br />\n",
|
||||||
cn->is_ssl ? "https" : "http", cn->virtualhostreq, cn->filereq);
|
cn->is_ssl ? "https" : "http", cn->server_name, cn->filereq);
|
||||||
special_write(cn, buf, strlen(buf));
|
special_write(cn, buf, strlen(buf));
|
||||||
cn->state = STATE_DOING_DIR;
|
cn->state = STATE_DOING_DIR;
|
||||||
}
|
}
|
||||||
@ -320,6 +318,7 @@ void procsendhead(struct connstruct *cn)
|
|||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
|
time_t now = cn->timeout - CONFIG_HTTP_TIMEOUT;
|
||||||
char date[32];
|
char date[32];
|
||||||
|
int file_exists;
|
||||||
|
|
||||||
/* are we trying to access a file over the HTTP connection instead of a
|
/* are we trying to access a file over the HTTP connection instead of a
|
||||||
* HTTPS connection? Or is this directory disabled? */
|
* HTTPS connection? Or is this directory disabled? */
|
||||||
@ -340,31 +339,19 @@ void procsendhead(struct connstruct *cn)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (stat(cn->actualfile, &stbuf) == -1)
|
file_exists = stat(cn->actualfile, &stbuf);
|
||||||
{
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
|
||||||
if (stat(cn->actualfile, &stbuf) == -1 && trycgi_withpathinfo(cn) == 0)
|
|
||||||
{
|
|
||||||
/* We Try To Find A CGI */
|
|
||||||
proccgi(cn, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
if (iscgi(cn->actualfile))
|
if (file_exists != -1 && cn->is_cgi)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
|
||||||
/* An executable file? */
|
|
||||||
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
|
|
||||||
{
|
{
|
||||||
|
/* A non-executable file, or directory? */
|
||||||
send_error(cn, 404);
|
send_error(cn, 404);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
|
proccgi(cn);
|
||||||
|
|
||||||
proccgi(cn, 0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -373,10 +360,10 @@ void procsendhead(struct connstruct *cn)
|
|||||||
if (isdir(cn->actualfile))
|
if (isdir(cn->actualfile))
|
||||||
{
|
{
|
||||||
char tbuf[MAXREQUESTLENGTH];
|
char tbuf[MAXREQUESTLENGTH];
|
||||||
sprintf(tbuf, "%s%s", cn->actualfile, index_file);
|
snprintf(tbuf, MAXREQUESTLENGTH, "%s%s", cn->actualfile, index_file);
|
||||||
|
|
||||||
if (stat(tbuf, &stbuf) != -1)
|
if ((file_exists = stat(tbuf, &stbuf)) != -1)
|
||||||
strcat(cn->actualfile, index_file);
|
my_strncpy(cn->actualfile, tbuf, MAXREQUESTLENGTH);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_HTTP_DIRECTORIES)
|
#if defined(CONFIG_HTTP_DIRECTORIES)
|
||||||
@ -387,22 +374,12 @@ void procsendhead(struct connstruct *cn)
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
if (file_exists == -1)
|
||||||
/* If the index is a CGI file, handle it like any other CGI */
|
{
|
||||||
if (iscgi(cn->actualfile))
|
send_error(cn, 404);
|
||||||
{
|
return;
|
||||||
/* Set up CGI script */
|
|
||||||
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
|
|
||||||
{
|
|
||||||
send_error(cn, 404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
proccgi(cn, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(date, ctime(&now));
|
strcpy(date, ctime(&now));
|
||||||
@ -412,7 +389,7 @@ void procsendhead(struct connstruct *cn)
|
|||||||
cn->if_modified_since >= stbuf.st_mtime))
|
cn->if_modified_since >= stbuf.st_mtime))
|
||||||
{
|
{
|
||||||
snprintf(buf, sizeof(buf), "HTTP/1.1 304 Not Modified\nServer: "
|
snprintf(buf, sizeof(buf), "HTTP/1.1 304 Not Modified\nServer: "
|
||||||
"axhttpd V%s\nDate: %s\n", ssl_version(), date);
|
"%s\nDate: %s\n", server_version, date);
|
||||||
special_write(cn, buf, strlen(buf));
|
special_write(cn, buf, strlen(buf));
|
||||||
cn->state = STATE_WANT_TO_READ_HEAD;
|
cn->state = STATE_WANT_TO_READ_HEAD;
|
||||||
return;
|
return;
|
||||||
@ -437,9 +414,9 @@ void procsendhead(struct connstruct *cn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\n"
|
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: %s\n"
|
||||||
"Content-Type: %s\nContent-Length: %ld\n"
|
"Content-Type: %s\nContent-Length: %ld\n"
|
||||||
"Date: %sLast-Modified: %s\n", ssl_version(),
|
"Date: %sLast-Modified: %s\n", server_version,
|
||||||
getmimetype(cn->actualfile), (long) stbuf.st_size,
|
getmimetype(cn->actualfile), (long) stbuf.st_size,
|
||||||
date, ctime(&stbuf.st_mtime)); /* ctime() has a \n on the end */
|
date, ctime(&stbuf.st_mtime)); /* ctime() has a \n on the end */
|
||||||
|
|
||||||
@ -514,18 +491,24 @@ void procsendfile(struct connstruct *cn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_HTTP_HAS_CGI)
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
static void proccgi(struct connstruct *cn, int has_pathinfo)
|
#define CGI_ARG_SIZE 14
|
||||||
|
|
||||||
|
static void proccgi(struct connstruct *cn)
|
||||||
{
|
{
|
||||||
int tpipe[2];
|
int tpipe[2];
|
||||||
char *myargs[5];
|
char *myargs[2];
|
||||||
char buf[MAXREQUESTLENGTH];
|
char cgienv[CGI_ARG_SIZE][MAXREQUESTLENGTH];
|
||||||
|
char * cgiptr[CGI_ARG_SIZE+1];
|
||||||
|
const char *type = "HEAD";
|
||||||
|
int cgi_index = 0, i;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
int tmp_stdout;
|
int tmp_stdout;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: axhttpd V%s\n%s",
|
snprintf(cgienv[0], MAXREQUESTLENGTH,
|
||||||
ssl_version(), (cn->reqtype == TYPE_HEAD) ? "\n" : "");
|
"HTTP/1.1 200 OK\nServer: %s\n%s",
|
||||||
special_write(cn, buf, strlen(buf));
|
server_version, (cn->reqtype == TYPE_HEAD) ? "\n" : "");
|
||||||
|
special_write(cn, cgienv[0], strlen(cgienv[0]));
|
||||||
|
|
||||||
if (cn->reqtype == TYPE_HEAD)
|
if (cn->reqtype == TYPE_HEAD)
|
||||||
{
|
{
|
||||||
@ -533,6 +516,12 @@ static void proccgi(struct connstruct *cn, int has_pathinfo)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HTTP_VERBOSE
|
||||||
|
printf("[CGI]: %s:/%s\n", cn->is_ssl ? "https" : "http", cn->filereq);
|
||||||
|
TTY_FLUSH();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* win32 cgi is a bit too painful */
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
pipe(tpipe);
|
pipe(tpipe);
|
||||||
|
|
||||||
@ -560,144 +549,139 @@ static void proccgi(struct connstruct *cn, int has_pathinfo)
|
|||||||
|
|
||||||
close(tpipe[0]);
|
close(tpipe[0]);
|
||||||
close(tpipe[1]);
|
close(tpipe[1]);
|
||||||
myargs[0] = cn->actualfile;
|
|
||||||
myargs[1] = cn->cgiargs;
|
|
||||||
myargs[2] = NULL;
|
|
||||||
|
|
||||||
if (!has_pathinfo)
|
myargs[0] = cn->actualfile;
|
||||||
|
myargs[1] = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the cgi args. A url is defined by:
|
||||||
|
* http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO?$QUERY_STRING
|
||||||
|
* TODO: other CGI parameters?
|
||||||
|
*/
|
||||||
|
sprintf(cgienv[cgi_index++], "SERVER_SOFTWARE=%s", server_version);
|
||||||
|
strcpy(cgienv[cgi_index++], "DOCUMENT_ROOT=" CONFIG_HTTP_WEBROOT);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"SERVER_NAME=%s", cn->server_name);
|
||||||
|
sprintf(cgienv[cgi_index++], "SERVER_PORT=%d",
|
||||||
|
cn->is_ssl ? CONFIG_HTTP_HTTPS_PORT : CONFIG_HTTP_PORT);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"REQUEST_URI=%s", cn->uri_request);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"SCRIPT_NAME=%s", cn->filereq);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"PATH_INFO=%s", cn->uri_path_info);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"QUERY_STRING=%s", cn->uri_query);
|
||||||
|
snprintf(cgienv[cgi_index++], MAXREQUESTLENGTH,
|
||||||
|
"REMOTE_ADDR=%s", cn->remote_addr);
|
||||||
|
|
||||||
|
switch (cn->reqtype)
|
||||||
{
|
{
|
||||||
my_strncpy(cn->cgipathinfo, "/", MAXREQUESTLENGTH);
|
case TYPE_GET:
|
||||||
my_strncpy(cn->cgiscriptinfo, cn->filereq, MAXREQUESTLENGTH);
|
type = "GET";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_POST:
|
||||||
|
type = "POST";
|
||||||
|
sprintf(cgienv[cgi_index++],
|
||||||
|
"CONTENT_LENGTH=%d", cn->content_length);
|
||||||
|
strcpy(cgienv[cgi_index++],
|
||||||
|
"CONTENT_TYPE=application/x-www-form-urlencoded");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
execv(cn->actualfile, myargs);
|
sprintf(cgienv[cgi_index++], "REQUEST_METHOD=%s", type);
|
||||||
#else /* WIN32 */
|
|
||||||
_pipe(tpipe, 8192, O_BINARY| O_NOINHERIT);
|
|
||||||
|
|
||||||
myargs[0] = "sh";
|
if (cn->is_ssl)
|
||||||
myargs[1] = "-c";
|
strcpy(cgienv[cgi_index++], "HTTPS=on");
|
||||||
myargs[2] = &cn->filereq[1]; /* ignore the inital "/" */
|
|
||||||
myargs[3] = cn->cgiargs;
|
|
||||||
myargs[4] = NULL;
|
|
||||||
|
|
||||||
tmp_stdout = _dup(_fileno(stdout));
|
#ifdef CONFIG_PLATFORM_CYGWIN
|
||||||
_dup2(tpipe[1], _fileno(stdout));
|
/* TODO: find out why Lua needs this */
|
||||||
close(tpipe[1]);
|
strcpy(cgienv[cgi_index++], "PATH=/usr/bin");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* change to suit execution method */
|
if (cgi_index >= CGI_ARG_SIZE)
|
||||||
if (spawnl(P_NOWAIT, "c:\\Program Files\\cygwin\\bin\\sh.exe",
|
|
||||||
myargs[0], myargs[1], myargs[2], myargs[3], myargs[4]) == -1)
|
|
||||||
{
|
{
|
||||||
removeconnection(cn);
|
printf("Content-type: text/plain\n\nToo many CGI args\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dup2(tmp_stdout, _fileno(stdout));
|
/* copy across the pointer indexes */
|
||||||
close(tmp_stdout);
|
for (i = 0; i < cgi_index; i++)
|
||||||
cn->filedesc = tpipe[0];
|
cgiptr[i] = cgienv[i];
|
||||||
cn->state = STATE_WANT_TO_READ_FILE;
|
|
||||||
cn->close_when_done = 1;
|
|
||||||
|
|
||||||
for (;;)
|
cgiptr[i] = NULL;
|
||||||
{
|
execve(myargs[0], myargs, cgiptr);
|
||||||
procreadfile(cn);
|
printf("Content-type: text/plain\n\nshouldn't get here\n");
|
||||||
|
|
||||||
if (cn->filedesc == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
procsendfile(cn);
|
|
||||||
usleep(200000); /* don't know why this delay makes it work (yet) */
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int trycgi_withpathinfo(struct connstruct *cn)
|
static char * cgi_filetype_match(struct connstruct *cn, const char *fn)
|
||||||
{
|
|
||||||
char tpfile[MAXREQUESTLENGTH];
|
|
||||||
char fr_str[MAXREQUESTLENGTH];
|
|
||||||
char *fr_rs[MAXCGIARGS]; /* filereq splitted */
|
|
||||||
int i = 0, offset;
|
|
||||||
|
|
||||||
my_strncpy(fr_str, cn->filereq, MAXREQUESTLENGTH);
|
|
||||||
split(fr_str, fr_rs, MAXCGIARGS, '/');
|
|
||||||
|
|
||||||
while (fr_rs[i] != NULL)
|
|
||||||
{
|
|
||||||
snprintf(tpfile, sizeof(tpfile), "/%s%s",
|
|
||||||
cn->virtualhostreq, fr_str);
|
|
||||||
|
|
||||||
if (iscgi(tpfile) && isdir(tpfile) == 0)
|
|
||||||
{
|
|
||||||
/* We've found our CGI file! */
|
|
||||||
my_strncpy(cn->actualfile, tpfile, MAXREQUESTLENGTH);
|
|
||||||
my_strncpy(cn->cgiscriptinfo, fr_str, MAXREQUESTLENGTH);
|
|
||||||
offset = (fr_rs[i] + strlen(fr_rs[i])) - fr_str;
|
|
||||||
my_strncpy(cn->cgipathinfo, cn->filereq+offset, MAXREQUESTLENGTH);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(fr_rs[i]+strlen(fr_rs[i])) = '/';
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Couldn't find any CGIs :( */
|
|
||||||
*(cn->cgiscriptinfo) = '\0';
|
|
||||||
*(cn->cgipathinfo) = '\0';
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iscgi(const char *fn)
|
|
||||||
{
|
{
|
||||||
struct cgiextstruct *tp = cgiexts;
|
struct cgiextstruct *tp = cgiexts;
|
||||||
int fnlen, extlen;
|
|
||||||
|
|
||||||
fnlen = strlen(fn);
|
|
||||||
|
|
||||||
while (tp != NULL)
|
while (tp != NULL)
|
||||||
{
|
{
|
||||||
extlen = strlen(tp->ext);
|
char *t;
|
||||||
|
|
||||||
if (strcasecmp(fn+(fnlen-extlen), tp->ext) == 0)
|
if ((t = strstr(fn, tp->ext)) != NULL)
|
||||||
return 1;
|
{
|
||||||
|
|
||||||
|
t += strlen(tp->ext);
|
||||||
|
|
||||||
|
if (*t == '/' || *t == '\0')
|
||||||
|
{
|
||||||
|
if (strcmp(tp->ext, ".lua") == 0 || strcmp(tp->ext, ".lp") == 0)
|
||||||
|
cn->is_lua = 1;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
tp = tp->next;
|
tp = tp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void split(char *tp, char *sp[], int maxwords, char sc)
|
static void decode_path_info(struct connstruct *cn, char *path_info)
|
||||||
{
|
{
|
||||||
int i = 0;
|
char *cgi_delim;
|
||||||
|
|
||||||
while(1)
|
cn->is_cgi = 0;
|
||||||
|
cn->is_lua = 0;
|
||||||
|
*cn->uri_request = '\0';
|
||||||
|
*cn->uri_path_info = '\0';
|
||||||
|
*cn->uri_query = '\0';
|
||||||
|
|
||||||
|
my_strncpy(cn->uri_request, path_info, MAXREQUESTLENGTH);
|
||||||
|
|
||||||
|
/* query info? */
|
||||||
|
if ((cgi_delim = strchr(path_info, '?')))
|
||||||
{
|
{
|
||||||
/* Skip leading whitespace */
|
*cgi_delim = '\0';
|
||||||
while (*tp == sc) tp++;
|
my_strncpy(cn->uri_query, cgi_delim+1, MAXREQUESTLENGTH);
|
||||||
|
|
||||||
if (*tp == '\0')
|
|
||||||
{
|
|
||||||
sp[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i==maxwords-2)
|
|
||||||
{
|
|
||||||
sp[maxwords-2] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp[i] = tp;
|
|
||||||
|
|
||||||
while(*tp != sc && *tp != '\0')
|
|
||||||
tp++;
|
|
||||||
|
|
||||||
if (*tp == sc)
|
|
||||||
*tp++ = '\0';
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cgi_delim = cgi_filetype_match(cn, path_info)) != NULL)
|
||||||
|
{
|
||||||
|
cn->is_cgi = 1; /* definitely a CGI script */
|
||||||
|
|
||||||
|
/* path info? */
|
||||||
|
if (*cgi_delim != '\0')
|
||||||
|
{
|
||||||
|
my_strncpy(cn->uri_path_info, cgi_delim, MAXREQUESTLENGTH);
|
||||||
|
*cgi_delim = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the bit at the start must be the script name */
|
||||||
|
my_strncpy(cn->filereq, path_info, MAXREQUESTLENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_HTTP_HAS_CGI */
|
#endif /* CONFIG_HTTP_HAS_CGI */
|
||||||
|
|
||||||
/* Decode string %xx -> char (in place) */
|
/* Decode string %xx -> char (in place) */
|
||||||
@ -755,6 +739,15 @@ static void buildactualfile(struct connstruct *cn)
|
|||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
|
#if defined(CONFIG_HTTP_HAS_CGI)
|
||||||
|
/* use the lua launcher if this file has a lua extension */
|
||||||
|
if (cn->is_lua)
|
||||||
|
{
|
||||||
|
strcpy(cn->actualfile, CONFIG_HTTP_LUA_LAUNCHER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_HTTP_USE_CHROOT
|
#ifdef CONFIG_HTTP_USE_CHROOT
|
||||||
snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s", cn->filereq);
|
snprintf(cn->actualfile, MAXREQUESTLENGTH, "%s", cn->filereq);
|
||||||
#else
|
#else
|
||||||
@ -937,7 +930,7 @@ static int auth_check(struct connstruct *cn)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
send_authenticate(cn, cn->virtualhostreq);
|
send_authenticate(cn, cn->server_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user