Project

General

Profile

cgi_x-send-file.patch

Max_nl, 2011-05-08 19:03

View differences:

src/mod_cgi.c 2011-05-08 18:46:08.745960442 +0200
56 56
typedef struct {
57 57
	array *cgi;
58 58
	unsigned short execute_x_only;
59
	unsigned short allow_xsendfile;
59 60
} plugin_config;
60 61

  
61 62
typedef struct {
......
74 75
	pid_t pid;
75 76
	int fd;
76 77
	int fde_ndx; /* index into the fd-event buffer */
78
	int send_content_body;
77 79

  
78 80
	connection *remote_conn;  /* dumb pointer */
79 81
	plugin_data *plugin_data; /* dumb pointer */
......
89 91

  
90 92
	hctx->response = buffer_init();
91 93
	hctx->response_header = buffer_init();
94
	hctx->send_content_body = 1;
92 95

  
93 96
	return hctx;
94 97
}
......
152 155
	config_values_t cv[] = {
153 156
		{ "cgi.assign",                  NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
154 157
		{ "cgi.execute-x-only",          NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },     /* 1 */
158
		{ "cgi.allow-x-send-file",		 NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },     /* 2 */
155 159
		{ NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
156 160
	};
157 161

  
......
166 170
		assert(s);
167 171

  
168 172
		s->cgi    = array_init();
169
		s->execute_x_only = 0;
173
		s->execute_x_only  = 0;
174
		s->allow_xsendfile = 0;
170 175

  
171 176
		cv[0].destination = s->cgi;
172 177
		cv[1].destination = &(s->execute_x_only);
178
		cv[2].destination = &(s->allow_xsendfile);
173 179

  
174 180
		p->config_storage[i] = s;
175 181

  
......
228 234
	return 0;
229 235
}
230 236

  
231
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
237
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, handler_ctx *hctx) {
232 238
	char *ns;
233 239
	const char *s;
234 240
	int line = 0;
......
312 318
					con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
313 319
					con->parsed_response |= HTTP_CONNECTION;
314 320
				}
321
				// falthrough
322
			case 20:
323
				if (p->conf.allow_xsendfile && hctx->send_content_body
324
					&& (0 == strncasecmp(key, "X-LIGHTTPD-send-file", key_len) || 0 == strncasecmp(key, "X-Sendfile", key_len)) )
325
				{
326
					stat_cache_entry *sce;
327

  
328
					if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
329
						data_string *dcls;
330
						if (NULL == (dcls = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
331
							dcls = data_response_init();
332
						}
333

  
334
						/* found */
335
						http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
336
						hctx->send_content_body = 0; /* ignore the content */
337
						joblist_append(srv, con);
338

  
339
						buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
340
						buffer_copy_off_t(dcls->value, sce->st.st_size);
341
						dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
342
						if (dcls) dcls->free((data_unset*)dcls);
343

  
344
						con->parsed_response |= HTTP_CONTENT_LENGTH;
345
						con->response.content_length = sce->st.st_size;
346
					} else {
347
						log_error_write(srv, __FILE__, __LINE__, "sb",
348
							"send-file error: couldn't get stat_cache entry for:",
349
							ds->value);
350
						con->http_status = 502;
351
						hctx->send_content_body = 0;
352
						con->file_started = 1;
353
						break;
354
					}
355
				}
315 356
				break;
316 357
			case 14:
317 358
				if (0 == strncasecmp(key, "Content-Length", key_len)) {
......
359 400
			con->file_finished = 1;
360 401

  
361 402
			/* send final chunk */
362
			http_chunk_append_mem(srv, con, NULL, 0);
363
			joblist_append(srv, con);
403
			if ( hctx->send_content_body )
404
			{
405
				http_chunk_append_mem(srv, con, NULL, 0);
406
				joblist_append(srv, con);
407
			}
364 408

  
365 409
			return FDEVENT_HANDLED_FINISHED;
366 410
		}
......
473 517
					hctx->response_header->used = i + 1; /* the string + \0 */
474 518
					
475 519
					/* parse the response header */
476
					cgi_response_parse(srv, con, p, hctx->response_header);
520
					cgi_response_parse(srv, con, p, hctx->response_header, hctx);
477 521

  
478 522
					/* enable chunked-transfer-encoding */
479 523
					if (con->request.http_version == HTTP_VERSION_1_1 &&
......
481 525
						con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
482 526
					}
483 527

  
484
					if (blen > 0) {
528
					if (blen > 0 && hctx->send_content_body) {
485 529
						http_chunk_append_mem(srv, con, bstart, blen + 1);
486 530
						joblist_append(srv, con);
487 531
					}
......
489 533

  
490 534
				con->file_started = 1;
491 535
			}
492
		} else {
536
		} else if (hctx->send_content_body) {
493 537
			http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
494 538
			joblist_append(srv, con);
495 539
		}
......
1194 1238

  
1195 1239
	PATCH(cgi);
1196 1240
	PATCH(execute_x_only);
1241
	PATCH(allow_xsendfile);
1197 1242

  
1198 1243
	/* skip the first, the global context */
1199 1244
	for (i = 1; i < srv->config_context->used; i++) {
......
1211 1256
				PATCH(cgi);
1212 1257
			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.execute-x-only"))) {
1213 1258
				PATCH(execute_x_only);
1259
			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.allow-x-send-file"))) {
1260
				PATCH(allow_xsendfile);
1214 1261
			}
1215 1262
		}
1216 1263
	}