static int fcgi_read_request(fcgi_request *req) { fcgi_header hdr; int len, padding; unsigned char buf[FCGI_MAX_LENGTH+8]; req->keep = 0; req->closed = 0; req->in_len = 0; req->out_hdr = NULL; req->out_pos = req->out_buf; req->has_env = 1; if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_STDIN && len == 0) { if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } if (len + padding > FCGI_MAX_LENGTH) { return 0; } req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { if (safe_read(req, buf, len+padding) != len+padding) { return 0; } req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); #ifdef TCP_NODELAY if (req->keep && req->tcp && !req->nodelay) { # ifdef _WIN32 BOOL on = 1; # else int on = 1; # endif setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); req->nodelay = 1; } #endif switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1); break; case FCGI_AUTHORIZER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1); break; case FCGI_FILTER: fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1); break; default: return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_PARAMS && len > 0) { if (len + padding > FCGI_MAX_LENGTH) { return 0; } if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { req->keep = 0; return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } } else if (hdr.type == FCGI_GET_VALUES) { unsigned char *p = buf + sizeof(fcgi_header); zval *value; unsigned int zlen; fcgi_hash_bucket *q; if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } q = req->env.list; while (q != NULL) { if ((value = zend_hash_str_find(&fcgi_mgmt_vars, q->var, q->var_len)) == NULL) { continue; } zlen = Z_STRLEN_P(value); if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) { break; } if (q->var_len < 0x80) { *p++ = q->var_len; } else { *p++ = ((q->var_len >> 24) & 0xff) | 0x80; *p++ = (q->var_len >> 16) & 0xff; *p++ = (q->var_len >> 8) & 0xff; *p++ = q->var_len & 0xff; } if (zlen < 0x80) { *p++ = zlen; } else { *p++ = ((zlen >> 24) & 0xff) | 0x80; *p++ = (zlen >> 16) & 0xff; *p++ = (zlen >> 8) & 0xff; *p++ = zlen & 0xff; } memcpy(p, q->var, q->var_len); p += q->var_len; memcpy(p, Z_STRVAL_P(value), zlen); p += zlen; } len = p - buf - sizeof(fcgi_header); len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { req->keep = 0; return 0; } return 0; } else {
static int fcgi_read_request(fcgi_request *req) { fcgi_header hdr; int len, padding; unsigned char buf[FCGI_MAX_LENGTH+8]; req->keep = 0; req->closed = 0; req->in_len = 0; req->out_hdr = NULL; req->out_pos = req->out_buf; ALLOC_HASHTABLE(req->env); zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0); if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_STDIN && len == 0) { if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } if (len + padding > FCGI_MAX_LENGTH) { return 0; } req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { char *val; if (safe_read(req, buf, len+padding) != len+padding) { return 0; } req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: val = estrdup("RESPONDER"); zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_AUTHORIZER: val = estrdup("AUTHORIZER"); zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_FILTER: val = estrdup("FILTER"); zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; default: return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_PARAMS && len > 0) { if (len + padding > FCGI_MAX_LENGTH) { return 0; } if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { req->keep = 0; return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } } else if (hdr.type == FCGI_GET_VALUES) { unsigned char *p = buf + sizeof(fcgi_header); HashPosition pos; char * str_index; uint str_length; ulong num_index; int key_type; zval ** value; if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } zend_hash_internal_pointer_reset_ex(req->env, &pos); while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTENT) { int zlen; zend_hash_move_forward_ex(req->env, &pos); if (key_type != HASH_KEY_IS_STRING) { continue; } if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) { continue; } --str_length; zlen = Z_STRLEN_PP(value); if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) { break; } if (str_length < 0x80) { *p++ = str_length; } else { *p++ = ((str_length >> 24) & 0xff) | 0x80; *p++ = (str_length >> 16) & 0xff; *p++ = (str_length >> 8) & 0xff; *p++ = str_length & 0xff; } if (zlen < 0x80) { *p++ = zlen; } else { *p++ = ((zlen >> 24) & 0xff) | 0x80; *p++ = (zlen >> 16) & 0xff; *p++ = (zlen >> 8) & 0xff; *p++ = zlen & 0xff; } memcpy(p, str_index, str_length); p += str_length; memcpy(p, Z_STRVAL_PP(value), zlen); p += zlen; } len = p - buf - sizeof(fcgi_header); len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { req->keep = 0; return 0; } return 0; } else {
static int fcgi_read_request(fcgi_request *req) { fcgi_header hdr; int len, padding; unsigned char buf[FCGI_MAX_LENGTH+8]; req->keep = 0; req->in_len = 0; req->out_hdr = NULL; req->out_pos = req->out_buf; zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1); if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_STDIN && len == 0) { if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { char *val; if (safe_read(req, buf, len+padding) != len+padding) { return 0; } req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { case FCGI_RESPONDER: val = strdup("RESPONDER"); zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_AUTHORIZER: val = strdup("AUTHORIZER"); zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; case FCGI_FILTER: val = strdup("FILTER"); zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); break; default: return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; while (hdr.type == FCGI_PARAMS && len > 0) { if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || hdr.version < FCGI_VERSION_1) { req->keep = 0; return 0; } len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; padding = hdr.paddingLength; } } else if (hdr.type == FCGI_GET_VALUES) { int j; unsigned char *p = buf + sizeof(fcgi_header); if (safe_read(req, buf, len+padding) != len+padding) { req->keep = 0; return 0; } if (!fcgi_get_params(req, buf, buf+len)) { req->keep = 0; return 0; } for (j = 0; j < sizeof(fcgi_mgmt_vars)/sizeof(fcgi_mgmt_vars[0]); j++) { if (zend_hash_exists(&req->env, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].name_len+1) == 0) { sprintf((char*)p, "%c%c%s%c", fcgi_mgmt_vars[j].name_len, 1, fcgi_mgmt_vars[j].name, fcgi_mgmt_vars[j].val); p += fcgi_mgmt_vars[j].name_len + 3; } } len = p - buf - sizeof(fcgi_header); len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { req->keep = 0; return 0; } return 0; } else { return 0; } return 1; }