Feature #2313 ยป cgi_x-send-file.patch
src/mod_cgi.c 2011-05-08 18:46:08.745960442 +0200 | ||
---|---|---|
typedef struct {
|
||
array *cgi;
|
||
unsigned short execute_x_only;
|
||
unsigned short allow_xsendfile;
|
||
} plugin_config;
|
||
typedef struct {
|
||
... | ... | |
pid_t pid;
|
||
int fd;
|
||
int fde_ndx; /* index into the fd-event buffer */
|
||
int send_content_body;
|
||
connection *remote_conn; /* dumb pointer */
|
||
plugin_data *plugin_data; /* dumb pointer */
|
||
... | ... | |
hctx->response = buffer_init();
|
||
hctx->response_header = buffer_init();
|
||
hctx->send_content_body = 1;
|
||
return hctx;
|
||
}
|
||
... | ... | |
config_values_t cv[] = {
|
||
{ "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
|
||
{ "cgi.execute-x-only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
|
||
{ "cgi.allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
|
||
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
|
||
};
|
||
... | ... | |
assert(s);
|
||
s->cgi = array_init();
|
||
s->execute_x_only = 0;
|
||
s->execute_x_only = 0;
|
||
s->allow_xsendfile = 0;
|
||
cv[0].destination = s->cgi;
|
||
cv[1].destination = &(s->execute_x_only);
|
||
cv[2].destination = &(s->allow_xsendfile);
|
||
p->config_storage[i] = s;
|
||
... | ... | |
return 0;
|
||
}
|
||
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
|
||
static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, handler_ctx *hctx) {
|
||
char *ns;
|
||
const char *s;
|
||
int line = 0;
|
||
... | ... | |
con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
|
||
con->parsed_response |= HTTP_CONNECTION;
|
||
}
|
||
// falthrough
|
||
case 20:
|
||
if (p->conf.allow_xsendfile && hctx->send_content_body
|
||
&& (0 == strncasecmp(key, "X-LIGHTTPD-send-file", key_len) || 0 == strncasecmp(key, "X-Sendfile", key_len)) )
|
||
{
|
||
stat_cache_entry *sce;
|
||
if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
|
||
data_string *dcls;
|
||
if (NULL == (dcls = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
|
||
dcls = data_response_init();
|
||
}
|
||
/* found */
|
||
http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
|
||
hctx->send_content_body = 0; /* ignore the content */
|
||
joblist_append(srv, con);
|
||
buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
|
||
buffer_copy_off_t(dcls->value, sce->st.st_size);
|
||
dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
|
||
if (dcls) dcls->free((data_unset*)dcls);
|
||
con->parsed_response |= HTTP_CONTENT_LENGTH;
|
||
con->response.content_length = sce->st.st_size;
|
||
} else {
|
||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||
"send-file error: couldn't get stat_cache entry for:",
|
||
ds->value);
|
||
con->http_status = 502;
|
||
hctx->send_content_body = 0;
|
||
con->file_started = 1;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case 14:
|
||
if (0 == strncasecmp(key, "Content-Length", key_len)) {
|
||
... | ... | |
con->file_finished = 1;
|
||
/* send final chunk */
|
||
http_chunk_append_mem(srv, con, NULL, 0);
|
||
joblist_append(srv, con);
|
||
if ( hctx->send_content_body )
|
||
{
|
||
http_chunk_append_mem(srv, con, NULL, 0);
|
||
joblist_append(srv, con);
|
||
}
|
||
return FDEVENT_HANDLED_FINISHED;
|
||
}
|
||
... | ... | |
hctx->response_header->used = i + 1; /* the string + \0 */
|
||
|
||
/* parse the response header */
|
||
cgi_response_parse(srv, con, p, hctx->response_header);
|
||
cgi_response_parse(srv, con, p, hctx->response_header, hctx);
|
||
/* enable chunked-transfer-encoding */
|
||
if (con->request.http_version == HTTP_VERSION_1_1 &&
|
||
... | ... | |
con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
|
||
}
|
||
if (blen > 0) {
|
||
if (blen > 0 && hctx->send_content_body) {
|
||
http_chunk_append_mem(srv, con, bstart, blen + 1);
|
||
joblist_append(srv, con);
|
||
}
|
||
... | ... | |
con->file_started = 1;
|
||
}
|
||
} else {
|
||
} else if (hctx->send_content_body) {
|
||
http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
|
||
joblist_append(srv, con);
|
||
}
|
||
... | ... | |
PATCH(cgi);
|
||
PATCH(execute_x_only);
|
||
PATCH(allow_xsendfile);
|
||
/* skip the first, the global context */
|
||
for (i = 1; i < srv->config_context->used; i++) {
|
||
... | ... | |
PATCH(cgi);
|
||
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.execute-x-only"))) {
|
||
PATCH(execute_x_only);
|
||
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.allow-x-send-file"))) {
|
||
PATCH(allow_xsendfile);
|
||
}
|
||
}
|
||
}
|