Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | In althttpd.c, refactor some of the CGI processing logic as a preliminary step toward adding SCGI support. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
3e667aef3a1ffab709868ee1ca17a079 |
User & Date: | drh 2019-02-15 18:16:17.141 |
Context
2019-02-15
| ||
20:31 | Add SCGI support to the althttpd.c web server. (check-in: 201d18b836 user: drh tags: trunk) | |
20:14 | Preliminary support for SCGI in althttpd. (check-in: b3aaed91ba user: drh tags: althttpd-scgi) | |
18:16 | In althttpd.c, refactor some of the CGI processing logic as a preliminary step toward adding SCGI support. (check-in: 3e667aef3a user: drh tags: trunk) | |
17:00 | Enhancements to althttpd.c: Add the --input FILE command-line option to simplify debugging using lldb. Improvements to comments. (check-in: a537e6f3fc user: drh tags: trunk) | |
Changes
Changes to misc/althttpd.c.
︙ | ︙ | |||
259 260 261 262 263 264 265 266 267 268 269 270 271 272 | static int useTimeout = 1; /* True to use times */ static int standalone = 0; /* Run as a standalone server (no inetd) */ static int ipv6Only = 0; /* Use IPv6 only */ static int ipv4Only = 0; /* Use IPv4 only */ static struct rusage priorSelf; /* Previously report SELF time */ static struct rusage priorChild; /* Previously report CHILD time */ static int mxAge = 120; /* Cache-control max-age */ /* ** Double any double-quote characters in a string. */ static char *Escape(char *z){ int i, j; int n; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | static int useTimeout = 1; /* True to use times */ static int standalone = 0; /* Run as a standalone server (no inetd) */ static int ipv6Only = 0; /* Use IPv6 only */ static int ipv4Only = 0; /* Use IPv4 only */ static struct rusage priorSelf; /* Previously report SELF time */ static struct rusage priorChild; /* Previously report CHILD time */ static int mxAge = 120; /* Cache-control max-age */ static char *default_path = "/bin:/usr/bin"; /* Default PATH variable */ static char *gateway_interface = "CGI/1.0"; /* CGI version number */ /* ** Mapping between CGI variable names and values stored in ** global variables. */ static struct { char *zEnvName; char **pzEnvValue; } cgienv[] = { { "AUTH_TYPE", &zAuthType }, { "AUTH_CONTENT", &zAuthArg }, { "CONTENT_LENGTH", &zContentLength }, { "CONTENT_TYPE", &zContentType }, { "DOCUMENT_ROOT", &zHome }, { "GATEWAY_INTERFACE", &gateway_interface }, { "HTTP_ACCEPT", &zAccept }, { "HTTP_ACCEPT_ENCODING", &zAcceptEncoding }, { "HTTP_COOKIE", &zCookie }, { "HTTP_HOST", &zHttpHost }, { "HTTP_IF_MODIFIED_SINCE", &zIfModifiedSince }, { "HTTP_IF_NONE_MATCH", &zIfNoneMatch }, { "HTTP_REFERER", &zReferer }, { "HTTP_USER_AGENT", &zAgent }, { "PATH", &default_path }, { "PATH_INFO", &zPathInfo }, { "QUERY_STRING", &zQueryString }, { "REMOTE_ADDR", &zRemoteAddr }, { "REQUEST_METHOD", &zMethod }, { "REQUEST_URI", &zScript }, { "REMOTE_USER", &zRemoteUser }, { "SCRIPT_DIRECTORY", &zDir }, { "SCRIPT_FILENAME", &zFile }, { "SCRIPT_NAME", &zRealScript }, { "SERVER_NAME", &zServerName }, { "SERVER_PORT", &zServerPort }, { "SERVER_PROTOCOL", &zProtocol }, }; /* ** Double any double-quote characters in a string. */ static char *Escape(char *z){ int i, j; int n; |
︙ | ︙ | |||
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 | ** Count the number of "/" characters in a string. */ static int countSlashes(const char *z){ int n = 0; while( *z ) if( *(z++)=='/' ) n++; return n; } /* ** This routine processes a single HTTP request on standard input and ** sends the reply to standard output. If the argument is 1 it means ** that we are should close the socket without processing additional ** HTTP requests after the current request finishes. 0 means we are ** allowed to keep the connection open and to process additional requests. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 | ** Count the number of "/" characters in a string. */ static int countSlashes(const char *z){ int n = 0; while( *z ) if( *(z++)=='/' ) n++; return n; } /* ** A CGI or SCGI script has run and is sending its reply back across ** the channel "in". Process this reply into an appropriate HTTP reply. ** Close the "in" channel when done. */ static void CgiHandleReply(FILE *in){ int seenContentLength = 0; /* True if Content-length: header seen */ int contentLength = 0; /* The content length */ int nRes = 0; /* Bytes of payload */ int nMalloc = 0; /* Bytes of space allocated to aRes */ char *aRes = 0; /* Payload */ int c; /* Next character from in */ char *z; /* Pointer to something inside of zLine */ char zLine[1000]; /* One line of reply from the CGI script */ if( useTimeout ) alarm(15); while( fgets(zLine,sizeof(zLine),in) && !isspace(zLine[0]) ){ if( strncasecmp(zLine,"Location:",9)==0 ){ StartResponse("302 Redirect"); RemoveNewline(zLine); z = &zLine[10]; while( isspace(*z) ){ z++; } nOut += printf("Location: %s\r\n",z); }else if( strncasecmp(zLine,"Status:",7)==0 ){ int i; for(i=7; isspace(zLine[i]); i++){} nOut += printf("%s %s", zProtocol, &zLine[i]); strncpy(zReplyStatus, &zLine[i], 3); zReplyStatus[3] = 0; statusSent = 1; }else{ /* 123456789 12345 */ if( strncasecmp(zLine, "Content-length:", 15)==0 ){ seenContentLength = 1; contentLength = atoi(zLine+15); } StartResponse("200 OK"); nOut += printf("%s",zLine); } } /* Copy everything else thru without change or analysis. */ StartResponse("200 OK"); if( useTimeout ) alarm(60*5); if( seenContentLength ){ nOut += printf("%s", zLine); while( (contentLength--)>0 && (c = getc(in))!=EOF ){ putc(c,stdout); nOut++; } }else{ nRes = 0; nMalloc = 1000; aRes = malloc(nMalloc+1); if( aRes==0 ) Malfunction(600,"Out of memory: %d bytes", nMalloc); while( (c = getc(in))!=EOF ){ if( nRes>=nMalloc ){ nMalloc = nMalloc*2; aRes = realloc(aRes, nMalloc+1); if( aRes==0 ){ Malfunction(610, "Out of memory: %d bytes", nMalloc); } } aRes[nRes++] = c; } aRes[nRes] = 0; nOut += printf("Content-length: %d\r\n\r\n%s", nRes, aRes); free(aRes); } fclose(in); } /* ** This routine processes a single HTTP request on standard input and ** sends the reply to standard output. If the argument is 1 it means ** that we are should close the socket without processing additional ** HTTP requests after the current request finishes. 0 means we are ** allowed to keep the connection open and to process additional requests. |
︙ | ︙ | |||
1573 1574 1575 1576 1577 1578 1579 | /* Take appropriate action */ if( (statbuf.st_mode & 0100)==0100 && access(zFile,X_OK)==0 ){ /* ** The followings static variables are used to setup the environment ** for the CGI script */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | /* Take appropriate action */ if( (statbuf.st_mode & 0100)==0100 && access(zFile,X_OK)==0 ){ /* ** The followings static variables are used to setup the environment ** for the CGI script */ char *zBaseFilename; /* Filename without directory prefix */ /* If its executable, it must be a CGI program. Start by ** changing directories to the directory holding the program. */ if( chdir(zDir) ){ char zBuf[1000]; Malfunction(420, /* LOG: chdir() failed */ |
︙ | ︙ | |||
1697 1698 1699 1700 1701 1702 1703 | exit(0); } close(px[1]); in = fdopen(px[0], "rb"); } if( in==0 ){ CgiError(); | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < | < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < | 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 | exit(0); } close(px[1]); in = fdopen(px[0], "rb"); } if( in==0 ){ CgiError(); }else{ CgiHandleReply(in); } }else if( countSlashes(zRealScript)!=countSlashes(zScript) ){ /* If the request URI for static content contains material past the ** actual content file name, report that as a 404 error. */ NotFound(460); /* LOG: Excess URI content past static file name */ }else{ /* If it isn't executable then it ** must a simple file that needs to be copied to output. |
︙ | ︙ |