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

fixed POST issues in axhttpd

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@126 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich 2007-09-17 03:29:50 +00:00
parent 7c7e89b540
commit 1d263c9ab4
4 changed files with 200 additions and 12 deletions

View File

@ -60,7 +60,8 @@ release:
$(MAKE) -C config/scripts/config clean $(MAKE) -C config/scripts/config clean
-$(MAKE) clean -$(MAKE) clean
-@rm config/*.msi config/*.back.aip config/config.h config/.config* -@rm config/*.msi config/*.back.aip config/config.h config/.config*
@rm -fr $(STAGE) -@rm www/index.20*
-@rm -fr $(STAGE)
@echo "#define AXTLS_VERSION \"$(VERSION)\"" > ssl/version.h @echo "#define AXTLS_VERSION \"$(VERSION)\"" > ssl/version.h
cd ../; tar cvfz $(RELEASE).tar.gz --wildcards-match-slash --exclude .svn axTLS; cd -; cd ../; tar cvfz $(RELEASE).tar.gz --wildcards-match-slash --exclude .svn axTLS; cd -;

View File

@ -24,7 +24,7 @@
#ifdef CONFIG_HTTP_HAS_IPV6 #ifdef CONFIG_HTTP_HAS_IPV6
#define HAVE_IPV6 #define HAVE_IPV6
#endif #endif
#define MAXPOSTDATASIZE 30000
#define MAXREQUESTLENGTH 256 #define MAXREQUESTLENGTH 256
#define BLOCKSIZE 4096 #define BLOCKSIZE 4096
@ -88,6 +88,9 @@ struct connstruct
#if defined(CONFIG_HTTP_HAS_AUTHORIZATION) #if defined(CONFIG_HTTP_HAS_AUTHORIZATION)
char authorization[MAXREQUESTLENGTH]; char authorization[MAXREQUESTLENGTH];
#endif #endif
int post_read;
int post_state;
char *post_data;
}; };
struct serverstruct struct serverstruct
@ -125,7 +128,7 @@ void procreadhead(struct connstruct *cn);
void procsendhead(struct connstruct *cn); void procsendhead(struct connstruct *cn);
void procreadfile(struct connstruct *cn); void procreadfile(struct connstruct *cn);
void procsendfile(struct connstruct *cn); void procsendfile(struct connstruct *cn);
void read_post_data(struct connstruct *cn);
/* misc.c prototypes */ /* misc.c prototypes */
char *my_strncpy(char *dest, const char *src, size_t n); char *my_strncpy(char *dest, const char *src, size_t n);

View File

@ -24,6 +24,20 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "axhttp.h" #include "axhttp.h"
#if AXDEBUG
#define AXDEBUGSTART \
{ \
FILE *dout; \
dout = fopen("/var/log/axdebug", "a"); \
#define AXDEBUGEND \
fclose(dout); \
}
#else /* AXDEBUG */
#define AXDEBUGSTART
#define AXDEBUGEND
#endif /* AXDEBUG */
struct serverstruct *servers; struct serverstruct *servers;
struct connstruct *usedconns; struct connstruct *usedconns;
struct connstruct *freeconns; struct connstruct *freeconns;
@ -161,6 +175,7 @@ int main(int argc, char *argv[])
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
addcgiext(CONFIG_HTTP_CGI_EXTENSIONS); addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
printf("addcgiext %s\n",CONFIG_HTTP_CGI_EXTENSIONS);
#endif #endif
#if defined(CONFIG_HTTP_VERBOSE) #if defined(CONFIG_HTTP_VERBOSE)
printf("%s: listening on ports %d (http) and %d (https)\n", printf("%s: listening on ports %d (http) and %d (https)\n",
@ -176,6 +191,7 @@ int main(int argc, char *argv[])
setuid(32767); setuid(32767);
#endif #endif
#ifdef CONFIG_HTTP_IS_DAEMON #ifdef CONFIG_HTTP_IS_DAEMON
fprintf(stderr, "ERR: fork is not working on uclinux\n");
if (fork() > 0) /* parent will die */ if (fork() > 0) /* parent will die */
exit(0); exit(0);
@ -283,6 +299,9 @@ int main(int argc, char *argv[])
FD_ISSET(to->networkdesc, &rfds)) FD_ISSET(to->networkdesc, &rfds))
{ {
active--; active--;
if (to->post_state)
read_post_data(to);
else
procreadhead(to); procreadhead(to);
} }

View File

@ -54,6 +54,20 @@ static void decode_path_info(struct connstruct *cn, char *path_info);
static int auth_check(struct connstruct *cn); static int auth_check(struct connstruct *cn);
#endif #endif
#if AXDEBUG
#define AXDEBUGSTART \
{ \
FILE *axdout; \
axdout = fopen("/var/log/axdebug", "a"); \
#define AXDEBUGEND \
fclose(axdout); \
}
#else /* AXDEBUG */
#define AXDEBUGSTART
#define AXDEBUGEND
#endif /* AXDEBUG */
/* Returns 1 if elems should continue being read, 0 otherwise */ /* Returns 1 if elems should continue being read, 0 otherwise */
static int procheadelem(struct connstruct *cn, char *buf) static int procheadelem(struct connstruct *cn, char *buf)
{ {
@ -267,11 +281,113 @@ static void urlencode(const uint8_t *s, char *t)
#endif #endif
int init_read_post_data(char *buf, char *data, struct connstruct *cn, int old_rv)
{
char *next;
int rv;
char *post_data;
rv=old_rv;
next=data;
/* Too much Post data to send. MAXPOSTDATASIZE should be
configured (now it can be chaged in the header file) */
if (cn->content_length > MAXPOSTDATASIZE)
{
send_error(cn, 418);
return 0;
}
/* remove CRLF */
while ((*next == '\r' || *next == '\n') && (next < &buf[rv]))
next++;
if (cn->post_data == NULL)
{
cn->post_data = (char *) calloc(1, (cn->content_length + 1));
/* Allocate buffer for the POST data that will be used by proccgi
to send POST data to the CGI script */
if (cn->post_data == NULL)
{
printf("axhttpd: could not allocate memory for POST data\n");
TTY_FLUSH();
send_error(cn, 599);
return 0;
}
}
cn->post_state = 0;
cn->post_read = 0;
post_data = cn->post_data;
while (next < &buf[rv])
{
/*copy POST data to buffer*/
*post_data = *next;
post_data++;
next++;
cn->post_read++;
if (cn->post_read == cn->content_length)
{
/* No more POST data to be copied */
*post_data = '\0';
return 1;
}
}
/* More POST data has to be read. read_post_data will continue with that */
cn->post_state = 1;
return 0;
}
void read_post_data(struct connstruct *cn)
{
char buf[MAXREQUESTLENGTH*4], *next;
char *post_data;
int rv;
bzero(buf,MAXREQUESTLENGTH*4);
rv = special_read(cn, buf, sizeof(buf)-1);
if (rv <= 0)
{
if (rv < 0) /* really dead? */
removeconnection(cn);
return;
}
buf[rv] = '\0';
next = buf;
post_data = &cn->post_data[cn->post_read];
while (next < &buf[rv])
{
*post_data = *next;
post_data++;
next++;
cn->post_read++;
if (cn->post_read == cn->content_length)
{
/* No more POST data to be copied */
*post_data='\0';
cn->post_state = 0;
buildactualfile(cn);
cn->state = STATE_WANT_TO_SEND_HEAD;
return;
}
}
/* More POST data to read */
}
void procreadhead(struct connstruct *cn) void procreadhead(struct connstruct *cn)
{ {
char buf[MAXREQUESTLENGTH*4], *tp, *next; char buf[MAXREQUESTLENGTH*4], *tp, *next;
int rv; int rv;
bzero(buf,MAXREQUESTLENGTH*4);
rv = special_read(cn, buf, sizeof(buf)-1); rv = special_read(cn, buf, sizeof(buf)-1);
if (rv <= 0) if (rv <= 0)
{ {
@ -293,6 +409,12 @@ void procreadhead(struct connstruct *cn)
/* If we have a blank line, advance to next stage */ /* If we have a blank line, advance to next stage */
if (*next == '\r' || *next == '\n') if (*next == '\r' || *next == '\n')
{ {
if ((cn->reqtype == TYPE_POST)&&(cn->content_length > 0))
{
if (init_read_post_data(buf,next,cn,rv) == 0)
return;
}
buildactualfile(cn); buildactualfile(cn);
cn->state = STATE_WANT_TO_SEND_HEAD; cn->state = STATE_WANT_TO_SEND_HEAD;
return; return;
@ -349,6 +471,7 @@ void procsendhead(struct connstruct *cn)
file_exists = stat(cn->actualfile, &stbuf); file_exists = stat(cn->actualfile, &stbuf);
#if defined(CONFIG_HTTP_HAS_CGI) #if defined(CONFIG_HTTP_HAS_CGI)
if (file_exists != -1 && cn->is_cgi) if (file_exists != -1 && cn->is_cgi)
{ {
if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile)) if ((stbuf.st_mode & S_IEXEC) == 0 || isdir(cn->actualfile))
@ -503,12 +626,13 @@ void procsendfile(struct connstruct *cn)
static void proccgi(struct connstruct *cn) static void proccgi(struct connstruct *cn)
{ {
int tpipe[2]; int tpipe[2], spipe[2];
char *myargs[2]; char *myargs[2];
char cgienv[CGI_ARG_SIZE][MAXREQUESTLENGTH]; char cgienv[CGI_ARG_SIZE][MAXREQUESTLENGTH];
char * cgiptr[CGI_ARG_SIZE+4]; char * cgiptr[CGI_ARG_SIZE+4];
const char *type = "HEAD"; const char *type = "HEAD";
int cgi_index = 0, i; int cgi_index = 0, i;
pid_t pid;
#ifdef WIN32 #ifdef WIN32
int tmp_stdout; int tmp_stdout;
#endif #endif
@ -531,10 +655,41 @@ static void proccgi(struct connstruct *cn)
/* win32 cgi is a bit too painful */ /* win32 cgi is a bit too painful */
#ifndef WIN32 #ifndef WIN32
pipe(tpipe); /* set up pipe that is used for sending POST query data to CGI script*/
if (cn->reqtype == TYPE_POST)
if (fork() > 0) /* parent */
{ {
if (pipe(spipe) == -1)
{
printf("[CGI]: could not create pipe");
TTY_FLUSH();
return;
}
}
if (pipe(tpipe) == -1)
{
printf("[CGI]: could not create pipe");
TTY_FLUSH();
return;
}
#ifdef EMBED
if ((pid = vfork()) > 0) /* parent */
#else
if ((pid = fork()) > 0) /* parent */
#endif
{
/* Send POST query data to CGI script */
if ((cn->reqtype == TYPE_POST) && (cn->content_length > 0))
{
write(spipe[1], cn->post_data, cn->content_length);
close(spipe[0]);
close(spipe[1]);
/* free the memory that is allocated in read_post_data() */
free(cn->post_data);
cn->post_data = NULL;
}
/* Close the write descriptor */ /* Close the write descriptor */
close(tpipe[1]); close(tpipe[1]);
cn->filedesc = tpipe[0]; cn->filedesc = tpipe[0];
@ -543,6 +698,9 @@ static void proccgi(struct connstruct *cn)
return; return;
} }
if (pid < 0) /* fork failed */
exit(1);
/* The problem child... */ /* The problem child... */
/* Our stdout/stderr goes to the socket */ /* Our stdout/stderr goes to the socket */
@ -551,13 +709,10 @@ static void proccgi(struct connstruct *cn)
/* If it was a POST request, send the socket data to our stdin */ /* If it was a POST request, send the socket data to our stdin */
if (cn->reqtype == TYPE_POST) if (cn->reqtype == TYPE_POST)
dup2(cn->networkdesc, 0); dup2(spipe[0], 0);
else /* Otherwise we can shutdown the read side of the sock */ else /* Otherwise we can shutdown the read side of the sock */
shutdown(cn->networkdesc, 0); shutdown(cn->networkdesc, 0);
close(tpipe[0]);
close(tpipe[1]);
myargs[0] = cn->actualfile; myargs[0] = cn->actualfile;
myargs[1] = NULL; myargs[1] = NULL;
@ -617,7 +772,7 @@ static void proccgi(struct connstruct *cn)
if (cgi_index >= CGI_ARG_SIZE) if (cgi_index >= CGI_ARG_SIZE)
{ {
printf("Content-type: text/plain\n\nToo many CGI args\n"); printf("Content-type: text/plain\n\nToo many CGI args\n");
return; exit(1);
} }
/* copy across the pointer indexes */ /* copy across the pointer indexes */
@ -631,6 +786,7 @@ static void proccgi(struct connstruct *cn)
execve(myargs[0], myargs, cgiptr); execve(myargs[0], myargs, cgiptr);
printf("Content-type: text/plain\n\nshouldn't get here\n"); printf("Content-type: text/plain\n\nshouldn't get here\n");
exit(1);
#endif #endif
} }
@ -815,10 +971,14 @@ static void buildactualfile(struct connstruct *cn)
if (cn->is_lua) if (cn->is_lua)
#ifdef CONFIG_PLATFORM_CYGWIN #ifdef CONFIG_PLATFORM_CYGWIN
sprintf(cn->actualfile, "%s/bin/cgi.exe", CONFIG_HTTP_LUA_PREFIX); sprintf(cn->actualfile, "%s/bin/cgi.exe", CONFIG_HTTP_LUA_PREFIX);
#else
#ifdef EMBED
sprintf(cn->actualfile, "%s", CONFIG_HTTP_LUA_PREFIX);
#else #else
sprintf(cn->actualfile, "%s/bin/cgi", CONFIG_HTTP_LUA_PREFIX); sprintf(cn->actualfile, "%s/bin/cgi", CONFIG_HTTP_LUA_PREFIX);
#endif #endif
#endif #endif
#endif
} }
static int sanitizefile(const char *buf) static int sanitizefile(const char *buf)
@ -1007,6 +1167,11 @@ static void send_error(struct connstruct *cn, int err)
text = title; text = title;
break; break;
case 418:
title = "POST data size is to large";
text = title;
break;
default: default:
title = "Unknown"; title = "Unknown";
text = "Unknown"; text = "Unknown";