diff options
author | nork <nork@FreeBSD.org> | 2003-10-17 16:11:55 +0800 |
---|---|---|
committer | nork <nork@FreeBSD.org> | 2003-10-17 16:11:55 +0800 |
commit | 66cc5a6957e8acbcbab2366db67c416193082fae (patch) | |
tree | f8c16d2dd20f92880fc8687abdd93ca8ff98ff93 | |
parent | 531176ba457bc17de67ef0947a794e54c930b458 (diff) | |
download | freebsd-ports-gnome-66cc5a6957e8acbcbab2366db67c416193082fae.tar.gz freebsd-ports-gnome-66cc5a6957e8acbcbab2366db67c416193082fae.tar.zst freebsd-ports-gnome-66cc5a6957e8acbcbab2366db67c416193082fae.zip |
Add pserv 3.0.b1, a portable and small webserver written in C.
PR: ports/58119
Submitted by: Alex Dupre <sysadmin@alexdupre.com>
-rw-r--r-- | www/Makefile | 1 | ||||
-rw-r--r-- | www/pserv/Makefile | 32 | ||||
-rw-r--r-- | www/pserv/distinfo | 1 | ||||
-rw-r--r-- | www/pserv/files/patch-Makefile | 17 | ||||
-rw-r--r-- | www/pserv/files/patch-handlers.c | 362 | ||||
-rw-r--r-- | www/pserv/files/patch-handlers.h | 10 | ||||
-rw-r--r-- | www/pserv/files/patch-main.c | 386 | ||||
-rw-r--r-- | www/pserv/files/patch-main.h | 65 | ||||
-rw-r--r-- | www/pserv/files/patch-mime.c | 34 | ||||
-rw-r--r-- | www/pserv/files/patch-mime_types.dat | 7 | ||||
-rw-r--r-- | www/pserv/files/patch-pserv.conf | 18 | ||||
-rw-r--r-- | www/pserv/files/pserv.sh | 25 | ||||
-rw-r--r-- | www/pserv/pkg-descr | 11 | ||||
-rw-r--r-- | www/pserv/pkg-plist | 4 |
14 files changed, 973 insertions, 0 deletions
diff --git a/www/Makefile b/www/Makefile index 7129ee175fd2..36827f7755ec 100644 --- a/www/Makefile +++ b/www/Makefile @@ -443,6 +443,7 @@ SUBDIR += pound SUBDIR += privoxy SUBDIR += privoxy+ipv6 + SUBDIR += pserv SUBDIR += publicfile SUBDIR += pwebstats SUBDIR += py-HTMLgen diff --git a/www/pserv/Makefile b/www/pserv/Makefile new file mode 100644 index 000000000000..728ffd2120db --- /dev/null +++ b/www/pserv/Makefile @@ -0,0 +1,32 @@ +# New ports collection makefile for: pserv +# Date created: Wed Oct 15 14:16:14 CEST 2003 +# Whom: Alex Dupre <sysadmin@alexdupre.com> +# +# $FreeBSD$ +# + +PORTNAME= pserv +PORTVERSION= 3.0.b1 +CATEGORIES= www +MASTER_SITES= ${MASTER_SITE_SOURCEFORGE} +MASTER_SITE_SUBDIR= ${PORTNAME} +DISTNAME= ${PORTNAME}-22-Sep-03 +EXTRACT_SUFX= .tar.Z + +MAINTAINER= sysadmin@alexdupre.com +COMMENT= A portable and small webserver written in C + +WRKSRC= ${WRKDIR}/${PORTNAME} +USE_REINPLACE= yes + +post-patch: + @${REINPLACE_CMD} "s|%%PREFIX%%|${PREFIX}|g;s|%%LOCALBASE%%|${LOCALBASE}|g" \ + ${WRKSRC}/pserv.conf + +do-install: + ${INSTALL_PROGRAM} ${WRKSRC}/pserv ${PREFIX}/sbin/ + ${INSTALL_DATA} ${WRKSRC}/mime_types.dat ${PREFIX}/etc/mime.types + ${INSTALL_DATA} ${WRKSRC}/pserv.conf ${PREFIX}/etc/ + ${INSTALL_SCRIPT} ${FILESDIR}/pserv.sh ${PREFIX}/etc/rc.d/ + +.include <bsd.port.mk> diff --git a/www/pserv/distinfo b/www/pserv/distinfo new file mode 100644 index 000000000000..6eda3d6fbb2c --- /dev/null +++ b/www/pserv/distinfo @@ -0,0 +1 @@ +MD5 (pserv-22-Sep-03.tar.Z) = 4895631b730836c9202d5ac28b05f0fa diff --git a/www/pserv/files/patch-Makefile b/www/pserv/files/patch-Makefile new file mode 100644 index 000000000000..270d791c64a1 --- /dev/null +++ b/www/pserv/files/patch-Makefile @@ -0,0 +1,17 @@ +--- Makefile.orig Mon Sep 8 20:05:54 2003 ++++ Makefile Thu Oct 16 14:24:50 2003 +@@ -1,11 +1,11 @@ + #Change the following to your needs +-CC = gcc ++CC ?= gcc + #insert here flags, eg. optimizations +-CFLAGS = -Wall -O3 +-LIBS = -lnsl -lsocket + SRCS = main.c handlers.c mime.c log.c + OBJS = main.o handlers.o mime.o log.o + PROGRAM = pserv ++ ++all : $(PROGRAM) + + $(PROGRAM) : $(OBJS) + $(CC) -o $(PROGRAM) $(OBJS) $(LIBS) diff --git a/www/pserv/files/patch-handlers.c b/www/pserv/files/patch-handlers.c new file mode 100644 index 000000000000..2a943605a18d --- /dev/null +++ b/www/pserv/files/patch-handlers.c @@ -0,0 +1,362 @@ +--- handlers.c.orig Thu Sep 18 15:26:48 2003 ++++ handlers.c Thu Oct 16 14:16:05 2003 +@@ -24,6 +24,7 @@ + #endif + + extern char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */ ++extern char homePath[MAX_PATH_LEN+1]; /* root for PHP scripts exec */ + extern int port; /* server port */ + extern char defaultFileName[MAX_PATH_LEN+1]; /* default name for index, default or similar file */ + +@@ -262,12 +263,33 @@ + newArgv[i] = NULL; /* we correctly terminate argv */ + + i = 0; ++ if (req.contentLength != -1) ++ { ++ sprintf(newEnvp[i++], "CONTENT_LENGTH=%ld", req.contentLength); ++ strcpy(newEnvp[i], "CONTENT_TYPE="); ++ strcat(newEnvp[i++], req.contentType); ++ } ++ strcpy(newEnvp[i], "SERVER_NAME="); ++ strcat(newEnvp[i++], DEFAULT_SERVER_NAME); + strcpy(newEnvp[i], "SERVER_SOFTWARE="); + strcat(newEnvp[i], SERVER_SOFTWARE_STR); + strcat(newEnvp[i], "/"); + strcat(newEnvp[i++], SERVER_VERSION_STR); ++ strcpy(newEnvp[i], "SERVER_PROTOCOL="); ++ strcat(newEnvp[i++], req.protocolVersion); + strcpy(newEnvp[i], "REQUEST_METHOD="); + strcat(newEnvp[i++], req.method); ++ strcpy(newEnvp[i], "REMOTE_ADDR="); ++ strcat(newEnvp[i++], req.address); ++ strcpy(newEnvp[i], "HTTP_USER_AGENT="); ++ strcat(newEnvp[i++], req.userAgent); ++ if (req.cookie[0] != '\0') ++ { ++ strcpy(newEnvp[i], "HTTP_COOKIE="); ++ strcat(newEnvp[i++], req.cookie); ++ } ++ strcpy(newEnvp[i], "SCRIPT_FILENAME="); ++ strcat(newEnvp[i++], completedPath); + strcpy(newEnvp[i], "SCRIPT_NAME="); + strcat(newEnvp[i++], req.documentAddress); + strcpy(newEnvp[i], "GATEWAY_INTERFACE="); +@@ -302,13 +324,256 @@ + execve(completedPath, newArgv, newEnvp); + /* we reach this line only if an execution error occoured */ + /* logging will happen in the father */ +- printf("\n<HTML><HEAD><TITLE>CGI Error</TITLE></HEAD><BODY><H1>Cgi Exec error</H1></BODY></HTML>\n"); ++ printf("\n<HTML><HEAD><TITLE>CGI Error</TITLE></HEAD><BODY><H1>CGI Exec error</H1></BODY></HTML>\n"); + exit(-1); + } + return 0; + } + +-int dumpHeader(sock, filePath, mimeType, req) ++ ++#ifdef PHP ++int phpHandler(port, sock, phpFileName, completedPath, req, postStr) ++int port; ++int sock; ++char *phpFileName; ++char *completedPath; ++struct request req; ++char *postStr; ++{ ++ char envPath[MAX_PATH_LEN+1]; /* where to hold the envrion PATH parameter */ ++ char *relativePath; ++ char scriptWorkingDir[MAX_PATH_LEN+1]; ++ char **newArgv; ++ char **newEnvp; ++ int i; ++ int outStdPipe[2]; /* we will redirect the script output to a pipe so we can read it */ ++ int inStdPipe[2]; /* we will redirect the script input to a pipe so we can read it */ ++ int pid; /* we fork and execute inside the child the script */ ++ char pipeReadBuf[PIPE_READ_BUF+1]; ++ int howMany; ++ int totalSentFromPipe; /* ampunt of bytes sucked from the pipe and pushed in to the socket */ ++ int fatal; ++ ++ relativePath = strrchr(completedPath, '/'); ++ strncpy(scriptWorkingDir, completedPath, strlen(completedPath) - strlen(relativePath)); ++ scriptWorkingDir[strlen(completedPath) - strlen(relativePath)] = '\0'; ++ ++ /* first we create the pipes needed for stdout redirection */ ++ if (pipe(outStdPipe)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("Pipe creation error\n"); ++ return -1; ++#endif ++ } ++ if (pipe(inStdPipe)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("Pipe creation error\n"); ++ return -1; ++#endif ++ } ++ ++ ++ /* now we fork to subsequently execve */ ++ pid = fork(); ++ if (pid) ++ { /* this is the parent process */ ++ if (pid < 0) ++ { /* we check for creation error */ ++ printf ("Forking error during cgi exec: %d\n", errno); ++ return -1; ++ } ++ /* we close the unused end of the pipe */ ++ close(outStdPipe[WRITE]); ++ close(inStdPipe[READ]); ++ ++ if (!strcmp(req.method, "POST")) /* we have to feed the stdin of the script */ ++ { ++ if(!strlen(postStr)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("cannot post empty data\n"); ++#endif ++ return -1; ++ } ++ howMany = write(inStdPipe[WRITE], postStr, strlen(postStr)); ++ if (howMany < 0) ++ printf("Error during script pipe read.\n"); ++ } ++ totalSentFromPipe = 0; ++ fatal = NO; ++ howMany = 1; ++ while (howMany > 0 && !fatal) ++ { ++ howMany = read(outStdPipe[READ], &pipeReadBuf, PIPE_READ_BUF); ++ if (howMany < 0) ++ printf("Error during script pipe read.\n"); ++ else if (!howMany) ++ printf("Nothing read from script pipe.\n"); ++ else { ++ pipeReadBuf[howMany] = '\0'; ++ if (send(sock, pipeReadBuf, howMany, 0) < 0) ++ { ++ printf("error during CGI sock writing! %d\n", errno); ++ if (errno == EAGAIN) ++ printf("output resource temporarily not available\n"); ++ else if (errno == EPIPE) ++ { ++ printf("broken pipe during CGI out.\n"); ++ fatal = YES; ++ } else if (errno == EBADF) ++ { ++#ifdef PRINTF_DEBUG ++ printf("invalid out descriptor.\n"); ++#endif ++ fatal = YES; ++ } ++ } else ++ totalSentFromPipe += howMany; ++ } ++ } ++ /* now we finished and we clean up */ ++ wait(&i); ++ if (i) /* check if execution exited cleanly or with code */ ++ logWriter(LOG_CGI_FAILURE, NULL, 0, req, i); ++ else ++ logWriter(LOG_CGI_SUCCESS, NULL, totalSentFromPipe, req, 0); ++ close(outStdPipe[READ]); ++ close(inStdPipe[WRITE]); ++ } else ++ { /* this is the child process */ ++ /* now we do some environment setup work */ ++ newArgv = calloc(MAX_ARGV_LEN + 1, sizeof(char*)); ++ for (i = 0; i < MAX_ARGV_LEN + 1; i++) ++ { ++ newArgv[i] = calloc(MAX_PATH_LEN, sizeof(char)); ++ } ++ ++ newEnvp = calloc(MAX_ENVP_LEN + 1, sizeof(char*)); ++ for (i = 0; i < MAX_ENVP_LEN + 1; i++) ++ { ++ newEnvp[i] = calloc(MAX_PATH_LEN, sizeof(char)); ++ } ++ ++ ++ ++ /* extracting PATH env variable */ ++ i = 0; ++ while (environ && strncmp(environ[i], PATH_MATCH_STRING, strlen(PATH_MATCH_STRING))) ++ i++; ++ if(environ[i]) ++ strcpy(envPath, environ[i]); ++ else ++ envPath[0] = '\0'; /* maybe we should set some default? */ ++ ++ i = 0; ++ strcpy(newArgv[i++], phpFileName); /* here we should pass the phppath */ ++ strcpy(newArgv[i++], completedPath); /* here we should pass the scriptpath */ ++ if (strlen(req.queryString)) ++ { ++ int toParse; ++ int j, k; ++ ++ toParse = YES; ++ j = strlen(req.queryString); ++ while (toParse && j > 0) ++ { ++ if (req.queryString[j] == '=') ++ toParse = NO; ++ j--; ++ } ++ if (toParse) ++ { ++ j = 0; ++ k = 0; ++ howMany = strlen(req.queryString); ++ while (j < howMany) ++ { ++ if (req.queryString[j] == '+') ++ { ++ newArgv[i++][k] = '\0'; ++ k = 0; ++ } else ++ newArgv[i][k++] = req.queryString[j]; ++ j++; ++ } ++ i++; /* after all we will have at least one argument! */ ++ } ++ } ++ newArgv[i] = NULL; /* we correctly terminate argv */ ++ ++ i = 0; ++ if (req.contentLength != -1) ++ { ++ sprintf(newEnvp[i++], "CONTENT_LENGTH=%ld", req.contentLength); ++ strcpy(newEnvp[i], "CONTENT_TYPE="); ++ strcat(newEnvp[i++], req.contentType); ++ } ++ strcpy(newEnvp[i], "SERVER_NAME="); ++ strcat(newEnvp[i++], DEFAULT_SERVER_NAME); ++ strcpy(newEnvp[i], "SERVER_SOFTWARE="); ++ strcat(newEnvp[i], SERVER_SOFTWARE_STR); ++ strcat(newEnvp[i], "/"); ++ strcat(newEnvp[i++], SERVER_VERSION_STR); ++ strcpy(newEnvp[i], "SERVER_PROTOCOL="); ++ strcat(newEnvp[i++], req.protocolVersion); ++ strcpy(newEnvp[i], "REQUEST_METHOD="); ++ strcat(newEnvp[i++], req.method); ++ strcpy(newEnvp[i], "REMOTE_ADDR="); ++ strcat(newEnvp[i++], req.address); ++ strcpy(newEnvp[i], "HTTP_USER_AGENT="); ++ strcat(newEnvp[i++], req.userAgent); ++ if (req.cookie[0] != '\0') ++ { ++ strcpy(newEnvp[i], "HTTP_COOKIE="); ++ strcat(newEnvp[i++], req.cookie); ++ } ++ strcpy(newEnvp[i], "SCRIPT_FILENAME="); ++ strcat(newEnvp[i++], completedPath); ++ strcpy(newEnvp[i], "SCRIPT_NAME="); ++ strcat(newEnvp[i++], req.documentAddress); ++ strcpy(newEnvp[i], "GATEWAY_INTERFACE="); ++ strcat(newEnvp[i++], CGI_VERSION); ++ sprintf(newEnvp[i++], "SERVER_PORT=%d", port); ++ strcpy(newEnvp[i++], envPath); ++ strcpy(newEnvp[i], "QUERY_STRING="); ++ strcat(newEnvp[i++], req.queryString); ++ newEnvp[i] = NULL; ++ ++ /* we change the current working directory to the scripts one */ ++ if(chdir(scriptWorkingDir)) ++ { ++#ifdef PRINTF_DEBUG ++ printf("error while changing PWD in script execution: %d\n", errno); ++#endif ++ } ++ ++ close(outStdPipe[READ]); /* we close the unused end*/ ++ dup2(outStdPipe[WRITE], 1); /* we duplicate the pipe to the stdout */ ++ close(outStdPipe[WRITE]); /* we close the pipe, since we use the duplicate */ ++ ++ close(inStdPipe[WRITE]); /* we close the unused end*/ ++ dup2(inStdPipe[READ], 0); /* we duplicate the pipe to the stdin */ ++ close(inStdPipe[READ]); /* we close the pipe, since we use the duplicate */ ++ ++ ++ /* generate a reduced mimeHeader, no type, no size, etc */ ++ generateMimeHeader(sock, 200, "", NULL, req.protocolVersion, CGI_ONLY_HEADER); ++ ++ /* now we execute the script replacing the current child */ ++ execve(phpFileName, newArgv, newEnvp); ++ /* we reach this line only if an execution error occoured */ ++ /* logging will happen in the father */ ++ printf("\n<HTML><HEAD><TITLE>PHP Error</TITLE></HEAD><BODY><H1>PHP Exec error</H1></BODY></HTML>\n"); ++ exit(-1); ++ } ++ return 0; ++} ++#endif ++ ++int dumpHeader(port, sock, filePath, mimeType, req) ++int port; + int sock; + char filePath[]; + char mimeType[]; +@@ -351,11 +616,11 @@ + return -1; + } + stat(filePath, &fileStats); +- generateMimeHeader(sock, 200, mimeType, &fileStats, req.protocolVersion, FULL_HEADER); +- logWriter(LOG_GET_SUCCESS, req.documentAddress, (long int)fileStats.st_size, req, 0); + howMany = 0; + if (strncmp(mimeType, "text", 4)) /* check if it is a text type */ + { /* raw binary output routine */ ++ generateMimeHeader(sock, 200, mimeType, &fileStats, req.protocolVersion, FULL_HEADER); ++ logWriter(LOG_GET_SUCCESS, req.documentAddress, (long int)fileStats.st_size, req, 0); + fatal = NO; + retry = NO; + while(!feof(inFile) && !fatal) +@@ -399,11 +664,11 @@ + if (howMany > 0) + { + #ifdef ON_THE_FLY_CONVERSION +- { +- int i; +- for (i = 0; i < howMany; i++) +- if(outBuff[i] == '\r') outBuff[i] = '\n'; +- } ++ { ++ int i; ++ for (i = 0; i < howMany; i++) ++ if(outBuff[i] == '\r') outBuff[i] = '\n'; ++ } + #endif + if (send(sock, outBuff, howMany, 0) < 0) + { +@@ -449,7 +714,7 @@ + FILE *tempFile; + size_t generatedBytes; + char tempStr[MAX_PATH_LEN+1]; +- char linkStr[MAX_PATH_LEN+1]; ++ char linkStr[MAX_PATH_LEN+2]; + time_t currTime; + char timeStr[256]; + +@@ -497,10 +762,16 @@ + if (strcmp(dp->d_name, ".")) /* not self */ + { + if (strcmp(dp->d_name, "..")) ++ { + strcpy(linkStr, dp->d_name); +- else ++ if (dp->d_type == DT_DIR) ++ strcat(linkStr, "/"); ++ sprintf(tempStr, "<A HREF=\"%s\">%s</A><BR>\n", linkStr, linkStr); ++ } else ++ { + strcpy(linkStr, "Parent Directory"); +- sprintf(tempStr, "<A HREF=\"%s\">%s</A><BR>\n", dp->d_name, linkStr); ++ sprintf(tempStr, "<A HREF=\"%s/\">%s</A><BR>\n", dp->d_name, linkStr); ++ } + generatedBytes += strlen(tempStr); + fprintf(tempFile, "%s\n", tempStr); + } diff --git a/www/pserv/files/patch-handlers.h b/www/pserv/files/patch-handlers.h new file mode 100644 index 000000000000..939a714d8dca --- /dev/null +++ b/www/pserv/files/patch-handlers.h @@ -0,0 +1,10 @@ +--- handlers.h.orig Wed Oct 15 17:06:59 2003 ++++ handlers.h Wed Oct 15 17:07:08 2003 +@@ -19,6 +19,7 @@ + + /* handlers.c */ + int cgiHandler(); ++int phpHandler(); + int dumpHeader(); + int dumpFile(); + int generateIndex(); diff --git a/www/pserv/files/patch-main.c b/www/pserv/files/patch-main.c new file mode 100644 index 000000000000..e9ae61cbe1b6 --- /dev/null +++ b/www/pserv/files/patch-main.c @@ -0,0 +1,386 @@ +--- main.c.orig Mon Sep 22 10:39:24 2003 ++++ main.c Thu Oct 16 14:00:02 2003 +@@ -23,6 +23,7 @@ + char defaultFileName[MAX_PATH_LEN+1]; + char logFileName[MAX_PATH_LEN+1]; + char mimeTypesFileName[MAX_PATH_LEN+1]; ++char phpFileName[MAX_PATH_LEN+1]; + char cgiRoot[MAX_PATH_LEN+1]; /* root for CGI scripts exec */ + struct timeval sockTimeVal; + mimeData *mimeArray; /* here we will hold all MIME data, inited once, never to be changed */ +@@ -206,10 +207,10 @@ + int reqSize; + int readLines; + int tokenEnd; +- +- /* we copy the header lines to an array for easier parsing */ ++ ++ /* we copy the header lines to an array for easier parsing */ + /* but first we make sure that our string has a newline and an end */ +- req[BUFFER_SIZE] = '\0'; ++ req[BUFFER_SIZE] = '\0'; + reqSize = strlen(req); + req[reqSize] = '\n'; + reqSize++; +@@ -230,7 +231,7 @@ + for (k = 0; k < readLines; k++) + printf("%d - |%s|\n", k, reqArray[k]); + #endif +- ++ + /* first line: method, path and protocol version */ + /* we copy to a temporary buffer to be more secure against overflows */ + i = j = 0; +@@ -246,7 +247,7 @@ + else + tokenEnd = NO; + i++; +- ++ + /* we look for the document address */ + j = 0; + reqStruct->documentAddress[0] = '\0'; +@@ -259,14 +260,14 @@ + else + token[j] = '\0'; /* to make sure we have a string */ + /* now we need to convert some escapings from the path like %20 */ +- convertPercents(token, j); ++ convertPercents(token, j); + strcpy(reqStruct->documentAddress, token); /* copy back */ + if (reqArray[0][i] == '\0') + tokenEnd = YES; + else + tokenEnd = NO; + i++; +- ++ + /* we need now to separate path from query string ("?" separated) */ + if (reqArray[0][i-1] == '?') + { +@@ -282,7 +283,7 @@ + i++; + } + } +- ++ + /* we analyze the HTTP protocol version */ + /* default is 0.9 since that version didn't report itself */ + strcpy(reqStruct->protocolVersion, "HTTP/0.9"); +@@ -306,10 +307,13 @@ + else if (!strncmp(reqArray[1], "Connection: Keep-Alive", strlen("Connection: keep-alive"))) + reqStruct->keepAlive = YES; + +- /* user-agent, content-length and else */ ++ /* user-agent, content-length, content-type, cookie and else */ + i = 1; + j = NO; + reqStruct->userAgent[0] = '\0'; ++ reqStruct->contentLength = -1; ++ reqStruct->contentType[0] = '\0'; ++ reqStruct->cookie[0] = '\0'; + while (i < readLines) + { + if (!strncmp(reqArray[i], "User-Agent:", strlen("User-Agent:"))) +@@ -317,14 +321,28 @@ + strncpy(reqStruct->userAgent, &reqArray[i][strlen("User-Agent: ")], USER_AGENT_LEN - 1); + reqStruct->userAgent[USER_AGENT_LEN] = '\0'; + } +- else if (!strncmp(reqArray[i], "Content-Length:", strlen("Content-length:")) || !strncmp(reqArray[i], "Content-length:", strlen("Content-length:"))) +- { +- strcpy(token, &reqArray[i][strlen("Content-length: ")]); +- sscanf(token, "%ld", &(reqStruct->contentLength)); ++ else if (!strncmp(reqArray[i], "Content-Length:", strlen("Content-length:")) || !strncmp(reqArray[i], "Content-length:", strlen("Content-length:"))) ++ { ++ strcpy(token, &reqArray[i][strlen("Content-length: ")]); ++ sscanf(token, "%ld", &(reqStruct->contentLength)); + #ifdef PRINTF_DEBUG +- printf("content length %ld\n", reqStruct->contentLength); ++ printf("content length %ld\n", reqStruct->contentLength); + #endif +- } ++ } ++ else if (!strncmp(reqArray[i], "Content-Type:", strlen("Content-type:")) || !strncmp(reqArray[i], "Content-type:", strlen("Content-type:"))) ++ { ++ strncpy(reqStruct->contentType, &reqArray[i][strlen("Content-type: ")], CONTENT_TYPE_LEN - 1); ++#ifdef PRINTF_DEBUG ++ printf("content type %s\n", reqStruct->contentType); ++#endif ++ } ++ else if (!strncmp(reqArray[i], "Cookie:", strlen("Cookie:"))) ++ { ++ strncpy(reqStruct->cookie, &reqArray[i][strlen("Cookie: ")], MAX_COOKIE_LEN - 1); ++#ifdef PRINTF_DEBUG ++ printf("cookie %s\n", reqStruct->cookie); ++#endif ++ } + i++; + } + /* if we didn't find a User-Aget we fill in a (N)ot(R)ecognized */ +@@ -414,18 +432,39 @@ + /* we append the default file name */ + strcat(completeFilePath, defaultFileName); + analyzeExtension(mimeType, completeFilePath); +- dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ if (strncmp(mimeType, "application/x-httpd-php", 23)) ++#endif ++ dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ else ++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL); ++#endif + } + #else + /* we append the default file name */ + strcat(completeFilePath, defaultFileName); + analyzeExtension(mimeType, completeFilePath); +- dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ if (strncmp(mimeType, "application/x-httpd-php", 23)) ++#endif ++ dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ else ++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL); ++#endif + #endif + } else + { /* it is a plain file */ + analyzeExtension(mimeType, completeFilePath); +- dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ if (strncmp(mimeType, "application/x-httpd-php", 23)) ++#endif ++ dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ else ++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL); ++#endif + } + } + } else if (!strcmp(req.method, "HEAD")) +@@ -494,7 +533,14 @@ + strcat(completeFilePath, defaultFileName); + } + analyzeExtension(mimeType, completeFilePath); +- dumpHeader(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ if (strncmp(mimeType, "application/x-httpd-php", 23)) ++#endif ++ dumpFile(sock, completeFilePath, mimeType, req); ++#ifdef PHP ++ else ++ phpHandler(port, sock, phpFileName, completeFilePath, req, NULL); ++#endif + } + } else if (!strcmp(req.method, "POST")) + { +@@ -507,13 +553,6 @@ + int readFinished; + + printf("Handling of POST method\n"); +- /* first we check if the path contains the directory selected for cgi's and in case handle it */ +- if (strncmp(req.documentAddress, CGI_MATCH_STRING, strlen(CGI_MATCH_STRING))) +- { +- /* non cgi POST is not supported */ +- sayError(sock, UNHANDLED_METHOD, "", req); +- return -1; +- } + #ifdef PRINTF_DEBUG + printf ("begin of post handling\n"); + +@@ -523,9 +562,15 @@ + totalRead = 0; + stuckCounter = 0; + timeOutCounter = 0; +- while (!readFinished) +- { +- howMany = recv(newSocket, tempBuff, BUFFER_SIZE, 0); ++ ++ /* SECURITY: Avoid malicious Content-Length -- check \r\n\r\n\0 also */ ++ if (req.contentLength < 0 || req.contentLength >= BUFFER_SIZE-5) { ++ sayError(sock, 500, "", req); ++ return -1; ++ } ++ ++ /* SECURITY: Remove loop to prevent buffer overflow */ ++ howMany = recv(newSocket, tempBuff, req.contentLength+5, 0); + tempBuff[howMany] = '\0'; /* seems that some Unices need this */ + #ifdef PRINTF_DEBUG + printf ("read: %d\n%s\n", howMany, tempBuff); +@@ -579,16 +624,15 @@ + if (howMany == req.contentLength) + readFinished = YES; + } +- } + #ifdef PRINTF_DEBUG +- printf("total read %d\n", totalRead); ++ printf("total read %d\n", totalRead); + #endif +- if (totalRead == 0) +- { +- printf("Request read error\n"); +- } else +- { +- if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */ ++ if (totalRead == 0) ++ { ++ printf("Request read error\n"); ++ } else ++ { ++ if (buff[totalRead - 1] != '\n') /* we need a trailing \n or the script will wait forever */ + { + buff[totalRead++] = '\n'; + buff[totalRead] = '\0'; +@@ -596,7 +640,77 @@ + #ifdef PRINTF_DEBUG + printf("buff: |%s|\n", buff); + #endif +- cgiHandler(port, sock, req, buff); ++ if (!strncmp(req.documentAddress, CGI_MATCH_STRING, strlen(CGI_MATCH_STRING))) ++ { ++ cgiHandler(port, sock, req, buff); ++ } else ++ { ++#ifdef PHP ++ strcpy(completeFilePath, homePath); ++ strcat(completeFilePath, req.documentAddress); ++ /* now we check if the given path tries to get out of the root */ ++ { ++ int i,j; ++ int sL; ++ char dirName[MAX_PATH_LEN+1]; ++ int depthCount = 0; ++ ++ sL = strlen(req.documentAddress); ++ dirName[0] = '\0'; ++ if (sL > 3) { ++ dirName[0] = req.documentAddress[1]; ++ dirName[1] = req.documentAddress[2]; ++ dirName[2] = req.documentAddress[3]; ++ dirName[3] ='\0'; ++ if (!strcmp(dirName, "../")) ++ { ++ sayError(sock, FORBIDDEN, req.documentAddress, req); ++ return -1; ++ } ++ } ++ j = 0; ++ for (i = 1; i < sL; i++) { ++ if (req.documentAddress[i] == '/') ++ { ++ dirName[j] = '\0'; ++ if (strcmp(dirName, "..")) ++ depthCount ++; ++ else ++ depthCount--; ++ j = 0; ++ } else ++ dirName[j++] = req.documentAddress[i]; ++ } ++ if (depthCount < 0) ++ { ++ sayError(sock, FORBIDDEN, req.documentAddress, req); ++ return -1; ++ } ++ } ++ /* now we check if the given file is a directory or a plain file */ ++ stat(completeFilePath, &fileStats); ++ if ((fileStats.st_mode & S_IFDIR) == S_IFDIR) ++ { ++ /* if does not end with a slash, we get an error */ ++ if(completeFilePath[strlen(completeFilePath)-1] != '/') ++ { ++ sayError(sock, NOT_FOUND, req.documentAddress, req); ++ return -1; ++ } ++ /* we append the default file name */ ++ strcat(completeFilePath, defaultFileName); ++ } ++ analyzeExtension(mimeType, completeFilePath); ++ if (strncmp(mimeType, "application/x-httpd-php", 23)) ++ { ++#endif ++ /* non cgi POST is not supported */ ++ sayError(sock, UNHANDLED_METHOD, "", req); ++ return -1; ++#ifdef PHP ++ } else phpHandler(port, sock, phpFileName, completeFilePath, req, buff); ++#endif ++ } + } + } else + { +@@ -625,7 +739,7 @@ + f = fopen(configFile, "r"); + if (f == NULL) + { +- printf("Error opening config file. Setting defaults.\n"); ++ printf("Config file not found. Setting defaults.\n"); + *serverPort = DEFAULT_PORT; + *maxChildren = DEFAULT_MAX_CHILDREN; + strcpy(homePath, DEFAULT_DOCS_LOCATION); +@@ -634,7 +748,9 @@ + sockTimeVal.tv_usec = DEFAULT_USEC_TO; + strcpy(logFileName, DEFAULT_LOG_FILE); + strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); ++ strcpy(phpFileName, DEFAULT_PHP_FILE); + strcpy(cgiRoot, DEFAULT_CGI_ROOT); ++ initMimeTypes(); + return -1; + } + if (!feof(f)) fscanf(f, "%s %s", str1, str2); +@@ -735,11 +851,25 @@ + if (mimeTypesFileName == NULL) + { + strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); +- printf("Error reading mimeTypesFileName from file, setting default, %s\n", mimeTypesFileName); ++ printf("Error reading mimeTypesFile from file, setting default, %s\n", mimeTypesFileName); + } + } else { + strcpy(mimeTypesFileName, DEFAULT_MIME_FILE); +- printf("Error reading mimeTypesFileName from file, setting default, %s\n", mimeTypesFileName); ++ printf("Error reading mimeTypesFile from file, setting default, %s\n", mimeTypesFileName); ++ } ++ if (!feof(f)) fscanf(f, "%s %s", str1, str2); ++ if (str1 != NULL && str2 != NULL && !strcmp(str1, "phpFile")) ++ { ++ sscanf(str2, "%s", phpFileName); ++ if (logFileName == NULL) ++ { ++ strcpy(phpFileName, DEFAULT_LOG_FILE); ++ printf("Error reading phpFile from file, setting default, %s\n", phpFileName); ++ } ++ } else ++ { ++ strcpy(phpFileName, DEFAULT_PHP_FILE); ++ printf("Error reading phpFile from file, setting default, %s\n", phpFileName); + } + if (!feof(f)) fscanf(f, "%s %s", str1, str2); + if (str1 != NULL && str2 != NULL && !strcmp(str1, "cgiRoot")) +@@ -775,6 +905,7 @@ + int readFinished; + struct request gottenReq; + int isKeepAlive; ++ int bool; + struct sockaddr_in listenName; /* data struct for the listen port */ + struct sockaddr_in acceptedSockStruct; /* sockaddr for the internetworking */ + int acceptedSocketLen; /* size of the structure */ +@@ -808,9 +939,16 @@ + printf("socket creation error occoured\n"); + return -1; + } ++ bool = 1; ++ error = setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)); ++ if (error == -1) ++ { if (errno == EADDRINUSE) ++ printf("set socket option error occoured\n"); ++ return -1; ++ } + error = bind (theSocket, (struct sockaddr*) &listenName, sizeof(listenName)); + if (error == -1) +- { ++ { if (errno == EADDRINUSE) + printf("socket binding error occoured\n"); + return -2; + } diff --git a/www/pserv/files/patch-main.h b/www/pserv/files/patch-main.h new file mode 100644 index 000000000000..4419788ac639 --- /dev/null +++ b/www/pserv/files/patch-main.h @@ -0,0 +1,65 @@ +--- main.h.orig Fri Sep 19 00:36:03 2003 ++++ main.h Thu Oct 16 13:52:18 2003 +@@ -24,11 +24,12 @@ + + + /* --- CPP parsing options --- */ +-#define PRINTF_DEBUG /* enable this to print some debugging messages */ ++#undef PRINTF_DEBUG /* enable this to print some debugging messages */ + #undef ON_THE_FLY_CONVERSION /* enable this for line ending conversion */ + #undef BRAIN_DEAD_CAST /* if your compiler is brainwashed and does not cast standard types.h structures */ + #define FORKING_SERVER /* enables to fork for every request */ + #define AUTO_INDEX /* enables auto-index of directories */ ++#define PHP /* enables transparent PHP support */ + + /* --- Configure options --- */ + #define CONFIG_FILE_NAME "pserv.conf" +@@ -39,19 +40,19 @@ + #define MIME_TYPE_DEFAULT "application/octet-stream" + + /* configuration file location */ +-#define DEFAULT_CONFIG_LOCATION "/export/home/multix/pserv/" +-//#define DEFAULT_CONFIG_LOCATION "/Users/multix/Documents/code/pserv/" ++#define DEFAULT_CONFIG_LOCATION "/usr/local/etc/" + + /* hard-wired defaults, if loading of config file fails */ +-#define DEFAULT_PORT 2000 ++#define DEFAULT_PORT 80 + #define DEFAULT_MAX_CHILDREN 5 +-#define DEFAULT_DOCS_LOCATION "/export/home/multix/public_html" ++#define DEFAULT_DOCS_LOCATION "/usr/local/www/data" + #define DEFAULT_FILE_NAME "index.html" + #define DEFAULT_SEC_TO 1 + #define DEFAULT_USEC_TO 100 +-#define DEFAULT_LOG_FILE "/export/home/multix/pserv/pserv.log" +-#define DEFAULT_MIME_FILE "/export/home/multix/pserv/mime_types.dat" +-#define DEFAULT_CGI_ROOT "/export/home/multix/public_html/cgi-bin" ++#define DEFAULT_LOG_FILE "/var/log/pserv.log" ++#define DEFAULT_MIME_FILE "/usr/local/etc/mime.types" ++#define DEFAULT_PHP_FILE "/usr/local/bin/php" ++#define DEFAULT_CGI_ROOT "/usr/local/www/cgi-bin" + #define DEFAULT_SERVER_NAME "localhost" + + /* amount of connections queued in listening */ +@@ -120,9 +121,11 @@ + #define ADDRESS_LEN 16 + #define METHOD_LEN 16 + #define PROTOCOL_LEN 16 ++#define CONTENT_TYPE_LEN 256 + #define USER_AGENT_LEN 256 + #define MAX_QUERY_STRING_LEN 1024 + #define MAX_PATH_LEN 1024 ++#define MAX_COOKIE_LEN 4096 + + struct request + { +@@ -133,7 +136,9 @@ + char protocolVersion[PROTOCOL_LEN+1]; + int keepAlive; + char userAgent[USER_AGENT_LEN+1]; ++ char cookie[MAX_COOKIE_LEN+1]; + long int contentLength; ++ char contentType[CONTENT_TYPE_LEN+1]; + char rest[BUFFER_SIZE+1]; + }; + diff --git a/www/pserv/files/patch-mime.c b/www/pserv/files/patch-mime.c new file mode 100644 index 000000000000..8d4c7252c024 --- /dev/null +++ b/www/pserv/files/patch-mime.c @@ -0,0 +1,34 @@ +--- mime.c.orig Thu Sep 18 15:26:55 2003 ++++ mime.c Wed Oct 15 18:38:42 2003 +@@ -43,8 +43,8 @@ + f = fopen(mimeTypesFileName, "r"); + if (f == NULL) + { +- printf("Error opening mime types file. Setting defaults.\n"); +- entries = 3; ++ printf("Mime types file not found. Setting defaults.\n"); ++ entries = 6; + mimeArray = (mimeData *) calloc(entries, sizeof(mimeData)); + if (mimeArray == NULL) { + printf("Errory while allocating mime types Array. Exiting.\n"); +@@ -52,10 +52,16 @@ + } + strcpy(mimeArray[0].ext, "html"); + strcpy(mimeArray[0].type, "text/html"); +- strcpy(mimeArray[1].ext, "gif"); +- strcpy(mimeArray[1].type, "image/gif"); +- strcpy(mimeArray[2].ext, "jpg"); +- strcpy(mimeArray[2].type, "image/jpg"); ++ strcpy(mimeArray[1].ext, "htm"); ++ strcpy(mimeArray[1].type, "text/html"); ++ strcpy(mimeArray[2].ext, "gif"); ++ strcpy(mimeArray[2].type, "image/gif"); ++ strcpy(mimeArray[3].ext, "jpg"); ++ strcpy(mimeArray[3].type, "image/jpg"); ++ strcpy(mimeArray[4].ext, "png"); ++ strcpy(mimeArray[4].type, "image/png"); ++ strcpy(mimeArray[5].ext, "php"); ++ strcpy(mimeArray[5].type, "application/x-httpd-php"); + mimeEntries = entries; + return -1; + } diff --git a/www/pserv/files/patch-mime_types.dat b/www/pserv/files/patch-mime_types.dat new file mode 100644 index 000000000000..e2378527f61f --- /dev/null +++ b/www/pserv/files/patch-mime_types.dat @@ -0,0 +1,7 @@ +--- mime_types.dat.orig Wed Oct 15 15:57:08 2003 ++++ mime_types.dat Wed Oct 15 15:57:22 2003 +@@ -14,3 +14,4 @@ + tar application/x-tar + lha application/octet-stream + lzh application/octet-stream ++php application/x-httpd-php diff --git a/www/pserv/files/patch-pserv.conf b/www/pserv/files/patch-pserv.conf new file mode 100644 index 000000000000..1580f655cd41 --- /dev/null +++ b/www/pserv/files/patch-pserv.conf @@ -0,0 +1,18 @@ +--- pserv.conf.orig Wed Oct 15 16:18:05 2003 ++++ pserv.conf Wed Oct 15 16:20:01 2003 +@@ -1,9 +1,10 @@ +-port 80 ++port 80 + maxChildren 4 +-documentsPath /export/home/multix/public_html ++documentsPath %%PREFIX%%/www/data + defaultFile index.html + secTimeout 1 + uSecTimeout 100000 +-logFile /export/home/multix/pserv/pserv.log +-mimeTypesFile /export/home/multix/pserv/mime_types.dat +-cgiRoot /export/home/multix/public_html/cgi-bin ++logFile /var/log/pserv.log ++mimeTypesFile %%PREFIX%%/etc/mime.types ++phpFile %%LOCALBASE%%/bin/php ++cgiRoot %%PREFIX%%/www/cgi-bin diff --git a/www/pserv/files/pserv.sh b/www/pserv/files/pserv.sh new file mode 100644 index 000000000000..9930e58c7886 --- /dev/null +++ b/www/pserv/files/pserv.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +if ! PREFIX=$(expr $0 : "\(/.*\)/etc/rc\.d/${0##*/}\$"); then + echo "$0: Cannot determine the PREFIX" >&2 + exit 64 +fi + +case "$1" in +start) + if [ -x ${PREFIX}/sbin/pserv ]; then + ${PREFIX}/sbin/pserv > /dev/null & + echo -n ' pserv' + fi + ;; +stop) + killall pserv > /dev/null 2>&1 + echo -n ' pserv' + ;; +*) + echo "Usage: `basename $0` {start|stop}" >&2 + exit 64 + ;; +esac + +exit 0 diff --git a/www/pserv/pkg-descr b/www/pserv/pkg-descr new file mode 100644 index 000000000000..066df7a9ccc6 --- /dev/null +++ b/www/pserv/pkg-descr @@ -0,0 +1,11 @@ +pServ is a small, portable HTTP server. It is written in pure C for speed and +portability. It runs as a standalone program and does not require inetd. +It should be small enough to be used in a mobile computer or to be run on your +obsolete workstation you have somewhere. + +This port contains a patched version to support the execution of php scripts. + +WWW: http://sourceforge.net/projects/pserv/ + +- Alex Dupre +sysadmin@alexdupre.com diff --git a/www/pserv/pkg-plist b/www/pserv/pkg-plist new file mode 100644 index 000000000000..930e95b16861 --- /dev/null +++ b/www/pserv/pkg-plist @@ -0,0 +1,4 @@ +sbin/pserv +etc/mime.types +etc/pserv.conf +etc/rc.d/pserv.sh |