* Send SCGI header block */
| 256 | * Send SCGI header block |
| 257 | */ |
| 258 | static int send_headers(request_rec *r, proxy_conn_rec *conn) |
| 259 | { |
| 260 | char *buf, *cp, *bodylen; |
| 261 | const char *ns_len; |
| 262 | const apr_array_header_t *env_table; |
| 263 | const apr_table_entry_t *env; |
| 264 | int j; |
| 265 | apr_size_t len, bodylen_size; |
| 266 | apr_size_t headerlen = sizeof(CONTENT_LENGTH) |
| 267 | + sizeof(SCGI_MAGIC) |
| 268 | + sizeof(SCGI_PROTOCOL_VERSION); |
| 269 | |
| 270 | ap_add_common_vars(r); |
| 271 | ap_add_cgi_vars(r); |
| 272 | |
| 273 | /* |
| 274 | * The header blob basically takes the environment and concatenates |
| 275 | * keys and values using 0 bytes. There are special treatments here: |
| 276 | * - GATEWAY_INTERFACE and SCGI_MAGIC are dropped |
| 277 | * - CONTENT_LENGTH is always set and must be sent as the very first |
| 278 | * variable |
| 279 | * |
| 280 | * Additionally it's wrapped into a so-called netstring (see SCGI spec) |
| 281 | */ |
| 282 | env_table = apr_table_elts(r->subprocess_env); |
| 283 | env = (apr_table_entry_t *)env_table->elts; |
| 284 | for (j = 0; j < env_table->nelts; ++j) { |
| 285 | if ( (!strcmp(env[j].key, GATEWAY_INTERFACE)) |
| 286 | || (!strcmp(env[j].key, CONTENT_LENGTH)) |
| 287 | || (!strcmp(env[j].key, SCGI_MAGIC))) { |
| 288 | continue; |
| 289 | } |
| 290 | headerlen += strlen(env[j].key) + strlen(env[j].val) + 2; |
| 291 | } |
| 292 | bodylen = apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->remaining); |
| 293 | bodylen_size = strlen(bodylen) + 1; |
| 294 | headerlen += bodylen_size; |
| 295 | |
| 296 | ns_len = apr_psprintf(r->pool, "%" APR_SIZE_T_FMT ":", headerlen); |
| 297 | len = strlen(ns_len); |
| 298 | headerlen += len + 1; /* 1 == , */ |
| 299 | cp = buf = apr_palloc(r->pool, headerlen); |
| 300 | memcpy(cp, ns_len, len); |
| 301 | cp += len; |
| 302 | |
| 303 | memcpy(cp, CONTENT_LENGTH, sizeof(CONTENT_LENGTH)); |
| 304 | cp += sizeof(CONTENT_LENGTH); |
| 305 | memcpy(cp, bodylen, bodylen_size); |
| 306 | cp += bodylen_size; |
| 307 | memcpy(cp, SCGI_MAGIC, sizeof(SCGI_MAGIC)); |
| 308 | cp += sizeof(SCGI_MAGIC); |
| 309 | memcpy(cp, SCGI_PROTOCOL_VERSION, sizeof(SCGI_PROTOCOL_VERSION)); |
| 310 | cp += sizeof(SCGI_PROTOCOL_VERSION); |
| 311 | |
| 312 | for (j = 0; j < env_table->nelts; ++j) { |
| 313 | if ( (!strcmp(env[j].key, GATEWAY_INTERFACE)) |
| 314 | || (!strcmp(env[j].key, CONTENT_LENGTH)) |
| 315 | || (!strcmp(env[j].key, SCGI_MAGIC))) { |
no test coverage detected