225
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, int eol) {
225
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
232
232
buffer_copy_string_buffer(p->parse_response, in);
234
234
for (s = p->parse_response->ptr;
235
NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
236
s = ns + (eol == EOL_RN ? 2 : 1), line++) {
235
NULL != (ns = strchr(s, '\n'));
236
s = ns + 1, line++) {
237
237
const char *key, *value;
244
if (ns > s && ns[-1] == '\r') ns[-1] = '\0';
244
247
0 == strncmp(s, "HTTP/1.", 7)) {
245
248
/* non-parsed header ... we parse them anyway */
253
256
status = strtol(s+9, NULL, 10);
255
if (con->http_status >= 100 &&
256
con->http_status < 1000) {
257
260
/* we expected 3 digits and didn't got them */
258
261
con->parsed_response |= HTTP_STATUS;
259
262
con->http_status = status;
266
/* parse the headers */
265
268
if (NULL == (value = strchr(s, ':'))) {
266
269
/* we expect: "<key>: <value>\r\n" */
362
365
/* split header from body */
364
367
if (con->file_started == 0) {
368
int cp, eol = EOL_UNSET;
369
int is_header_end = 0;
371
373
buffer_append_string_buffer(hctx->response_header, hctx->response);
376
* we have to handle a few cases:
389
* and different mixes of \n and \r\n combinations
391
* Some users also forget about CGI and just send a response and hope
392
* we handle it. No headers, no header-content seperator
373
396
/* nph (non-parsed headers) */
374
if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
376
/* search for the \r\n\r\n or \n\n in the string */
377
for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
378
if (*c == ':') in_header = 1;
379
else if (*c == '\n') {
380
if (in_header == 0) {
381
/* got a response without a response header */
388
if (eol == EOL_UNSET) eol = EOL_N;
390
if (*(c+1) == '\n') {
395
} else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
396
if (in_header == 0) {
397
/* got a response without a response header */
404
if (eol == EOL_UNSET) eol = EOL_RN;
397
if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) is_header = 1;
399
for (i = 0; !is_header_end && i < hctx->response_header->used - 1; i++) {
400
char c = hctx->response_header->ptr[i];
406
* looks like we have a normal header
412
if (is_header == 0) {
413
/* we got a EOL but we don't seem to got a HTTP header */
421
* check if we saw a \n(\r)?\n sequence
424
((i - last_eol == 1) ||
425
(i - last_eol == 2 && hctx->response_header->ptr[i - 1] == '\r'))) {
422
438
/* no header, but a body */
424
440
if (con->request.http_version == HTTP_VERSION_1_1) {
428
444
http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
429
445
joblist_append(srv, con);
431
size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
432
size_t blen = hctx->response_header->used - hlen - 1;
434
/* a small hack: terminate after at the second \r */
435
hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
436
hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
451
* i still points to the char after the terminating EOL EOL
453
* put it on the last \n again
457
/* the body starts after the EOL */
458
bstart = hctx->response_header->ptr + (i + 1);
459
blen = (hctx->response_header->used - 1) - (i + 1);
461
/* string the last \r?\n */
462
if (i > 0 && (hctx->response_header->ptr[i - 1] == '\r')) {
466
hctx->response_header->ptr[i] = '\0';
467
hctx->response_header->used = i + 1; /* the string + \0 */
438
469
/* parse the response header */
439
cgi_response_parse(srv, con, p, hctx->response_header, eol);
470
cgi_response_parse(srv, con, p, hctx->response_header);
441
472
/* enable chunked-transfer-encoding */
442
473
if (con->request.http_version == HTTP_VERSION_1_1 &&
444
475
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
447
if ((hctx->response->used != hlen) && blen > 0) {
448
http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
479
http_chunk_append_mem(srv, con, bstart, blen + 1);
449
480
joblist_append(srv, con);
851
882
/* request.content_length < SSIZE_MAX, see request.c */
852
ltostr(buf, con->request.content_length);
883
LI_ltostr(buf, con->request.content_length);
853
884
cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
854
885
cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
855
886
cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));