2008-07-23 20:19:23 +00:00
|
|
|
|
2008-11-16 20:33:53 +00:00
|
|
|
#include <lighttpd/base.h>
|
|
|
|
#include <lighttpd/plugin_core.h>
|
2008-07-23 20:19:23 +00:00
|
|
|
|
2009-09-15 22:19:06 +00:00
|
|
|
#include <lighttpd/version.h>
|
|
|
|
|
2009-10-07 20:49:40 +00:00
|
|
|
#include <lighttpd/http_range_parser.h>
|
|
|
|
|
2008-09-18 07:14:57 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2010-02-13 14:54:48 +00:00
|
|
|
#include <sched.h>
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_list(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liAction *a;
|
2008-07-24 11:25:40 +00:00
|
|
|
guint i;
|
2010-05-07 18:54:50 +00:00
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2008-07-24 11:25:40 +00:00
|
|
|
|
2008-09-26 14:11:08 +00:00
|
|
|
if (!val) {
|
2008-08-09 15:20:12 +00:00
|
|
|
ERROR(srv, "%s", "need parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type == LI_VALUE_ACTION) {
|
2008-09-26 14:11:08 +00:00
|
|
|
a = val->data.val_action.action;
|
2009-07-09 20:17:24 +00:00
|
|
|
li_action_acquire(a);
|
2008-08-06 18:46:42 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_LIST) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
a = li_action_new_list();
|
2008-09-26 14:11:08 +00:00
|
|
|
for (i = 0; i < val->data.list->len; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liValue *oa = g_array_index(val->data.list, liValue*, i);
|
|
|
|
if (oa->type != LI_VALUE_ACTION) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected action at entry %u of list, got %s", i, li_value_type_string(oa->type));
|
|
|
|
li_action_release(srv, a);
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-26 14:11:08 +00:00
|
|
|
assert(srv == oa->data.val_action.srv);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_action_acquire(oa->data.val_action.action);
|
2008-09-26 14:11:08 +00:00
|
|
|
g_array_append_val(a->data.list, oa->data.val_action.action);
|
2008-07-24 11:25:40 +00:00
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_when(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liValue *val_cond, *val_act, *val_act_else;
|
|
|
|
liAction *a, *act = NULL, *act_else = NULL;
|
2010-05-07 18:54:50 +00:00
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2008-07-25 12:09:03 +00:00
|
|
|
|
2008-09-26 14:11:08 +00:00
|
|
|
if (!val) {
|
2008-08-09 15:20:12 +00:00
|
|
|
ERROR(srv, "%s", "need parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_LIST) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-26 14:11:08 +00:00
|
|
|
if (val->data.list->len == 2) {
|
|
|
|
val_act_else = NULL;
|
2008-08-27 14:39:30 +00:00
|
|
|
act_else = NULL;
|
2008-09-26 14:11:08 +00:00
|
|
|
} else if (val->data.list->len == 3) {
|
2009-07-08 19:06:07 +00:00
|
|
|
val_act_else = g_array_index(val->data.list, liValue*, 2);
|
2008-08-27 14:39:30 +00:00
|
|
|
} else {
|
2008-09-26 14:11:08 +00:00
|
|
|
ERROR(srv, "expected list with length 2 or 3, has length %u", val->data.list->len);
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
val_cond = g_array_index(val->data.list, liValue*, 0);
|
|
|
|
val_act = g_array_index(val->data.list, liValue*, 1);
|
2008-08-27 14:39:30 +00:00
|
|
|
|
2010-02-14 19:58:27 +00:00
|
|
|
if (NULL == val_cond || val_cond->type != LI_VALUE_CONDITION) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected condition as first parameter, got %s", li_value_type_string(val_cond->type));
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-02-14 19:58:27 +00:00
|
|
|
if (NULL == val_act || val_act->type == LI_VALUE_NONE) {
|
2009-01-10 13:46:11 +00:00
|
|
|
act = NULL;
|
2009-07-08 19:06:07 +00:00
|
|
|
} else if (val_act->type == LI_VALUE_ACTION) {
|
2009-01-10 13:46:11 +00:00
|
|
|
act = val_act->data.val_action.action;
|
|
|
|
} else {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected action as second parameter, got %s", li_value_type_string(val_act->type));
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-02-14 19:58:27 +00:00
|
|
|
if (NULL != val_act_else) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val_act_else->type == LI_VALUE_NONE) {
|
2009-01-10 13:46:11 +00:00
|
|
|
act_else = NULL;
|
2009-07-08 19:06:07 +00:00
|
|
|
} else if (val_act_else->type == LI_VALUE_ACTION) {
|
2009-01-10 13:46:11 +00:00
|
|
|
act_else = val_act_else->data.val_action.action;
|
|
|
|
} else {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected action as third parameter, got %s", li_value_type_string(val_act_else->type));
|
2009-01-10 13:46:11 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-27 14:39:30 +00:00
|
|
|
}
|
2009-07-09 20:17:24 +00:00
|
|
|
li_condition_acquire(val_cond->data.val_cond.cond);
|
2010-02-14 19:58:27 +00:00
|
|
|
if (NULL != act) li_action_acquire(act);
|
|
|
|
if (NULL != act_else) li_action_acquire(act_else);
|
2009-07-09 20:17:24 +00:00
|
|
|
a = li_action_new_condition(val_cond->data.val_cond.cond, act, act_else);
|
2008-07-24 11:25:40 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_set(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liValue *val_val, *val_name;
|
|
|
|
liAction *a;
|
2009-12-21 11:29:14 +00:00
|
|
|
UNUSED(p); UNUSED(userdata);
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2008-09-26 14:11:08 +00:00
|
|
|
if (!val) {
|
2008-08-09 15:20:12 +00:00
|
|
|
ERROR(srv, "%s", "need parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_LIST) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
2008-08-08 16:49:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-26 14:11:08 +00:00
|
|
|
if (val->data.list->len != 2) {
|
|
|
|
ERROR(srv, "expected list with length 2, has length %u", val->data.list->len);
|
2008-08-08 16:49:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
val_name = g_array_index(val->data.list, liValue*, 0);
|
|
|
|
val_val = g_array_index(val->data.list, liValue*, 1);
|
|
|
|
if (val_name->type != LI_VALUE_STRING) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected string as first parameter, got %s", li_value_type_string(val_name->type));
|
2008-08-08 16:49:00 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-05-07 18:54:50 +00:00
|
|
|
a = li_option_action(srv, wrk, val_name->data.string->str, val_val);
|
2008-08-08 16:49:00 +00:00
|
|
|
return a;
|
2009-06-25 12:22:54 +00:00
|
|
|
}
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
static gboolean core_setup_set(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-07-08 19:06:07 +00:00
|
|
|
liValue *val_val, *val_name;
|
2009-12-21 11:29:14 +00:00
|
|
|
UNUSED(p); UNUSED(userdata);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
|
|
|
if (!val) {
|
|
|
|
ERROR(srv, "%s", "need parameter");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_LIST) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
|
2008-10-25 12:53:57 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (val->data.list->len != 2) {
|
|
|
|
ERROR(srv, "expected list with length 2, has length %u", val->data.list->len);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-07-08 19:06:07 +00:00
|
|
|
val_name = g_array_index(val->data.list, liValue*, 0);
|
|
|
|
val_val = g_array_index(val->data.list, liValue*, 1);
|
|
|
|
if (val_name->type != LI_VALUE_STRING) {
|
2009-07-09 20:17:24 +00:00
|
|
|
ERROR(srv, "expected string as first parameter, got %s", li_value_type_string(val_name->type));
|
2008-10-25 12:53:57 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2009-07-09 20:17:24 +00:00
|
|
|
return li_plugin_set_default_option(srv, val_name->data.string->str, val_val);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_docroot(liVRequest *vr, gpointer param, gpointer *context) {
|
2008-12-09 23:23:27 +00:00
|
|
|
UNUSED(context);
|
2008-08-09 15:20:12 +00:00
|
|
|
|
2009-01-05 21:24:54 +00:00
|
|
|
g_string_truncate(vr->physical.doc_root, 0);
|
|
|
|
g_string_append_len(vr->physical.doc_root, GSTR_LEN((GString*) param));
|
|
|
|
|
2009-10-02 10:13:37 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "docroot: %s", vr->physical.doc_root->str);
|
|
|
|
}
|
2008-08-09 15:20:12 +00:00
|
|
|
|
2009-01-12 00:02:39 +00:00
|
|
|
/* build physical path: docroot + uri.path */
|
|
|
|
g_string_truncate(vr->physical.path, 0);
|
|
|
|
g_string_append_len(vr->physical.path, GSTR_LEN(vr->physical.doc_root));
|
2009-09-15 13:31:00 +00:00
|
|
|
if (vr->request.uri.path->len == 0 || vr->request.uri.path->str[0] != '/')
|
|
|
|
li_path_append_slash(vr->physical.path);
|
2009-01-12 00:02:39 +00:00
|
|
|
g_string_append_len(vr->physical.path, GSTR_LEN(vr->request.uri.path));
|
|
|
|
|
2009-10-02 10:13:37 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "physical path: %s", vr->physical.path->str);
|
|
|
|
}
|
2009-01-12 00:02:39 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-01-05 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static void core_docroot_free(liServer *srv, gpointer param) {
|
2009-01-05 21:24:54 +00:00
|
|
|
UNUSED(srv);
|
|
|
|
g_string_free(param, TRUE);
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_docroot(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-07-08 19:06:07 +00:00
|
|
|
if (!val || val->type != LI_VALUE_STRING) {
|
2009-01-05 21:24:54 +00:00
|
|
|
ERROR(srv, "%s", "docroot action expects a string parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-24 13:00:29 +00:00
|
|
|
return li_action_new_function(core_handle_docroot, NULL, core_docroot_free, li_value_extract_string(val));
|
2009-01-05 21:24:54 +00:00
|
|
|
}
|
|
|
|
|
2009-11-11 12:35:14 +00:00
|
|
|
typedef struct {
|
|
|
|
GString *prefix, *path;
|
|
|
|
} core_alias_config;
|
|
|
|
|
|
|
|
static liHandlerResult core_handle_alias(liVRequest *vr, gpointer _param, gpointer *context) {
|
|
|
|
GArray *param = _param;
|
|
|
|
guint i;
|
|
|
|
UNUSED(context);
|
|
|
|
|
|
|
|
for (i = 0; i < param->len; i++) {
|
|
|
|
core_alias_config ac = g_array_index(param, core_alias_config, i);
|
|
|
|
gsize preflen = ac.prefix->len;
|
|
|
|
gboolean isdir = FALSE;
|
|
|
|
|
|
|
|
if (preflen > 0 && ac.prefix->str[preflen-1] == '/') {
|
|
|
|
preflen--;
|
|
|
|
isdir = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (li_string_prefix(vr->request.uri.path, ac.prefix->str, preflen)) {
|
|
|
|
/* check if url has the form "prefix" or "prefix/.*" */
|
|
|
|
if (isdir && vr->request.uri.path->str[preflen] != '\0' && vr->request.uri.path->str[preflen] != '/') continue;
|
|
|
|
|
|
|
|
/* prefix matched */
|
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "alias path: %s", ac.path->str);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_truncate(vr->physical.doc_root, 0);
|
|
|
|
g_string_append_len(vr->physical.doc_root, GSTR_LEN(ac.path));
|
|
|
|
|
|
|
|
/* build physical path: docroot + uri.path */
|
|
|
|
g_string_truncate(vr->physical.path, 0);
|
|
|
|
g_string_append_len(vr->physical.path, GSTR_LEN(ac.path));
|
|
|
|
g_string_append_len(vr->physical.path, vr->request.uri.path->str + preflen, vr->request.uri.path->len - preflen);
|
|
|
|
|
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "alias physical path: %s", vr->physical.path->str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void core_alias_free(liServer *srv, gpointer _param) {
|
|
|
|
GArray *param = _param;
|
|
|
|
guint i;
|
|
|
|
UNUSED(srv);
|
|
|
|
|
|
|
|
for (i = 0; i < param->len; i++) {
|
|
|
|
core_alias_config ac = g_array_index(param, core_alias_config, i);
|
|
|
|
g_string_free(ac.prefix, TRUE);
|
|
|
|
g_string_free(ac.path, TRUE);
|
|
|
|
}
|
|
|
|
g_array_free(param, TRUE);
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_alias(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-11-11 12:35:14 +00:00
|
|
|
GArray *a = NULL;
|
|
|
|
GArray *vl, *vl1;
|
|
|
|
core_alias_config ac;
|
2010-05-07 18:54:50 +00:00
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-11-11 12:35:14 +00:00
|
|
|
|
|
|
|
if (!val || val->type != LI_VALUE_LIST) {
|
|
|
|
ERROR(srv, "%s", "unexpected or no parameter for alias action");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vl = val->data.list;
|
2009-11-11 12:47:47 +00:00
|
|
|
if (vl->len == 2 && g_array_index(vl, liValue*, 0)->type == LI_VALUE_STRING && g_array_index(vl, liValue*, 1)->type == LI_VALUE_STRING) {
|
2009-11-11 12:35:14 +00:00
|
|
|
a = g_array_sized_new(FALSE, TRUE, sizeof(core_alias_config), 1);
|
2010-01-24 13:00:29 +00:00
|
|
|
ac.prefix = li_value_extract_string(g_array_index(vl, liValue*, 0));
|
|
|
|
ac.path = li_value_extract_string(g_array_index(vl, liValue*, 1));
|
2009-11-11 12:35:14 +00:00
|
|
|
g_array_append_val(a, ac);
|
|
|
|
} else {
|
|
|
|
guint i;
|
|
|
|
a = g_array_sized_new(FALSE, TRUE, sizeof(core_alias_config), vl->len);
|
|
|
|
for (i = 0; i < vl->len; i++) {
|
|
|
|
if (g_array_index(vl, liValue*, i)->type != LI_VALUE_LIST) {
|
|
|
|
ERROR(srv, "%s", "unexpected entry in parameter for alias action");
|
|
|
|
goto error_free;
|
|
|
|
}
|
|
|
|
vl1 = g_array_index(vl, liValue*, i)->data.list;
|
|
|
|
if (g_array_index(vl1, liValue*, 0)->type == LI_VALUE_STRING && g_array_index(vl1, liValue*, 1)->type == LI_VALUE_STRING) {
|
2010-01-24 13:00:29 +00:00
|
|
|
ac.prefix = li_value_extract_string(g_array_index(vl1, liValue*, 0));
|
|
|
|
ac.path = li_value_extract_string(g_array_index(vl1, liValue*, 1));
|
2009-11-11 12:35:14 +00:00
|
|
|
g_array_append_val(a, ac);
|
|
|
|
} else {
|
|
|
|
ERROR(srv, "%s", "unexpected entry in parameter for alias action");
|
|
|
|
goto error_free;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return li_action_new_function(core_handle_alias, NULL, core_alias_free, a);
|
|
|
|
|
|
|
|
error_free:
|
|
|
|
core_alias_free(srv, a);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_index(liVRequest *vr, gpointer param, gpointer *context) {
|
|
|
|
liHandlerResult res;
|
2009-06-24 19:14:09 +00:00
|
|
|
guint i;
|
|
|
|
struct stat st;
|
|
|
|
gint err;
|
2009-06-25 20:13:58 +00:00
|
|
|
GString *file, *tmp_docroot, *tmp_path;
|
2009-06-24 19:14:09 +00:00
|
|
|
GArray *files = param;
|
|
|
|
|
|
|
|
UNUSED(context);
|
|
|
|
|
|
|
|
if (!vr->physical.doc_root->len) {
|
|
|
|
VR_ERROR(vr, "%s", "no docroot specified yet but index action called");
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2009-06-24 19:14:09 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
res = li_stat_cache_get(vr, vr->physical.path, &st, &err, NULL);
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_WAIT_FOR_EVENT)
|
|
|
|
return LI_HANDLER_WAIT_FOR_EVENT;
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_ERROR) {
|
2009-06-24 19:14:09 +00:00
|
|
|
/* we ignore errors here so a later action can deal with it (e.g. 'static') */
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-06-24 19:14:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!S_ISDIR(st.st_mode))
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-11-15 20:59:16 +00:00
|
|
|
/* need trailing slash */
|
|
|
|
if (vr->request.uri.path->len == 0 || vr->request.uri.path->str[vr->request.uri.path->len-1] != '/') {
|
|
|
|
li_vrequest_redirect_directory(vr);
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
2009-06-25 20:13:58 +00:00
|
|
|
/* we use two temporary strings here, one to append to docroot and one to append to physical path */
|
|
|
|
tmp_docroot = vr->wrk->tmp_str;
|
|
|
|
g_string_truncate(tmp_docroot, 0);
|
|
|
|
g_string_append_len(vr->wrk->tmp_str, GSTR_LEN(vr->physical.doc_root));
|
|
|
|
tmp_path = g_string_new_len(GSTR_LEN(vr->physical.path));
|
2009-06-24 19:14:09 +00:00
|
|
|
|
|
|
|
/* loop through the list to find a possible index file */
|
|
|
|
for (i = 0; i < files->len; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
file = g_array_index(files, liValue*, i)->data.string;
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-06-25 20:13:58 +00:00
|
|
|
if (file->str[0] == '/') {
|
|
|
|
/* entries beginning with a slash shall be looked up directly at the docroot */
|
|
|
|
g_string_truncate(tmp_docroot, vr->physical.doc_root->len);
|
|
|
|
g_string_append_len(tmp_docroot, GSTR_LEN(file));
|
2009-07-09 20:17:24 +00:00
|
|
|
res = li_stat_cache_get(vr, tmp_docroot, &st, &err, NULL);
|
2009-06-25 20:13:58 +00:00
|
|
|
} else {
|
|
|
|
g_string_truncate(tmp_path, vr->physical.path->len);
|
|
|
|
g_string_append_len(tmp_path, GSTR_LEN(file));
|
2009-07-09 20:17:24 +00:00
|
|
|
res = li_stat_cache_get(vr, tmp_path, &st, &err, NULL);
|
2009-06-25 20:13:58 +00:00
|
|
|
}
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_WAIT_FOR_EVENT) {
|
2009-06-25 20:13:58 +00:00
|
|
|
g_string_free(tmp_path, TRUE);
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_WAIT_FOR_EVENT;
|
2009-06-25 20:13:58 +00:00
|
|
|
}
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_GO_ON) {
|
2009-06-24 19:14:09 +00:00
|
|
|
/* file exists. change physical path */
|
2009-09-08 22:40:12 +00:00
|
|
|
if (file->str[0] == '/') {
|
2009-06-25 20:13:58 +00:00
|
|
|
g_string_truncate(vr->physical.path, vr->physical.doc_root->len);
|
2009-09-08 22:40:12 +00:00
|
|
|
g_string_truncate(vr->request.uri.path, 0);
|
|
|
|
}
|
2009-06-25 20:13:58 +00:00
|
|
|
|
2009-06-24 19:14:09 +00:00
|
|
|
g_string_append_len(vr->physical.path, GSTR_LEN(file));
|
2009-09-08 22:40:12 +00:00
|
|
|
g_string_append_len(vr->request.uri.path, GSTR_LEN(file));
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
2009-06-24 19:14:09 +00:00
|
|
|
VR_DEBUG(vr, "using index file: '%s'", file->str);
|
|
|
|
}
|
|
|
|
|
2009-06-25 20:13:58 +00:00
|
|
|
g_string_free(tmp_path, TRUE);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-06-24 19:14:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-25 20:13:58 +00:00
|
|
|
g_string_free(tmp_path, TRUE);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-06-24 19:14:09 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static void core_index_free(liServer *srv, gpointer param) {
|
2009-06-24 19:14:09 +00:00
|
|
|
guint i;
|
|
|
|
GArray *files = param;
|
|
|
|
|
|
|
|
UNUSED(srv);
|
|
|
|
|
|
|
|
for (i = 0; i < files->len; i++)
|
2009-07-09 20:17:24 +00:00
|
|
|
li_value_free(g_array_index(files, liValue*, i));
|
2009-06-24 19:14:09 +00:00
|
|
|
|
|
|
|
g_array_free(files, TRUE);
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_index(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-06-24 19:14:09 +00:00
|
|
|
GArray *files;
|
|
|
|
guint i;
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-06-24 19:14:09 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (!val || val->type != LI_VALUE_LIST) {
|
2009-06-24 19:14:09 +00:00
|
|
|
ERROR(srv, "%s", "index action expects a list of strings as parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
files = val->data.list;
|
|
|
|
|
|
|
|
for (i = 0; i < files->len; i++) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (g_array_index(files, liValue*, i)->type != LI_VALUE_STRING) {
|
2009-06-24 19:14:09 +00:00
|
|
|
ERROR(srv, "%s", "index action expects a list of strings as parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-24 13:00:29 +00:00
|
|
|
return li_action_new_function(core_handle_index, NULL, core_index_free, li_value_extract_list(val));
|
2009-06-24 19:14:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_static(liVRequest *vr, gpointer param, gpointer *context) {
|
2009-09-17 07:54:34 +00:00
|
|
|
int fd = -1;
|
2009-03-26 22:05:17 +00:00
|
|
|
struct stat st;
|
|
|
|
int err;
|
2009-07-08 19:06:07 +00:00
|
|
|
liHandlerResult res;
|
2010-01-24 20:30:41 +00:00
|
|
|
GArray *exclude_arr = CORE_OPTIONPTR(LI_CORE_OPTION_STATIC_FILE_EXCLUDE_EXTENSIONS).list;
|
2009-10-07 20:49:40 +00:00
|
|
|
static const gchar boundary[] = "fkj49sn38dcn3";
|
2009-03-01 20:16:58 +00:00
|
|
|
|
2009-01-05 21:24:54 +00:00
|
|
|
UNUSED(param);
|
|
|
|
UNUSED(context);
|
|
|
|
|
2010-04-04 15:07:24 +00:00
|
|
|
if (li_vrequest_is_handled(vr))
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
|
2009-03-17 13:21:20 +00:00
|
|
|
switch (vr->request.http_method) {
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HTTP_METHOD_GET:
|
|
|
|
case LI_HTTP_METHOD_HEAD:
|
2009-03-17 13:21:20 +00:00
|
|
|
break;
|
|
|
|
default:
|
2010-04-04 15:07:24 +00:00
|
|
|
if (!li_vrequest_handle_direct(vr)) {
|
|
|
|
return LI_HANDLER_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
vr->response.http_status = 405;
|
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Allow"), CONST_STR_LEN("GET, HEAD"));
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-03-17 13:21:20 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (vr->physical.path->len == 0) return LI_HANDLER_GO_ON;
|
2008-08-09 15:20:12 +00:00
|
|
|
|
2009-10-08 11:37:53 +00:00
|
|
|
if (exclude_arr) {
|
|
|
|
const gchar *basep = g_basename(vr->physical.path->str);
|
2009-10-08 12:33:47 +00:00
|
|
|
const GString base = li_const_gstring((gchar*) basep, vr->physical.path->len - (basep - vr->physical.path->str));
|
2009-10-08 11:37:53 +00:00
|
|
|
guint i;
|
|
|
|
|
|
|
|
for (i = 0; i < exclude_arr->len; i++) {
|
|
|
|
liValue *v = g_array_index(exclude_arr, liValue*, i);
|
|
|
|
if (li_string_suffix(&base, GSTR_LEN(v->data.string))) {
|
|
|
|
if (!li_vrequest_handle_direct(vr)) {
|
|
|
|
return LI_HANDLER_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
vr->response.http_status = 403;
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
res = li_stat_cache_get(vr, vr->physical.path, &st, &err, &fd);
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_WAIT_FOR_EVENT)
|
2009-03-26 22:05:17 +00:00
|
|
|
return res;
|
2008-08-09 15:20:12 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
2009-03-17 13:21:20 +00:00
|
|
|
VR_DEBUG(vr, "try serving static file: '%s'", vr->physical.path->str);
|
|
|
|
}
|
2009-01-11 23:24:27 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (res == LI_HANDLER_ERROR) {
|
2009-03-26 22:05:17 +00:00
|
|
|
/* open or fstat failed */
|
|
|
|
|
2009-03-26 22:33:28 +00:00
|
|
|
if (fd != -1)
|
2009-03-26 22:16:41 +00:00
|
|
|
close(fd);
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
if (!li_vrequest_handle_direct(vr)) {
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2009-03-26 22:05:17 +00:00
|
|
|
}
|
2009-03-01 20:16:58 +00:00
|
|
|
|
2009-03-26 22:05:17 +00:00
|
|
|
switch (err) {
|
2009-03-01 20:16:58 +00:00
|
|
|
case ENOENT:
|
2009-03-17 13:21:20 +00:00
|
|
|
case ENOTDIR:
|
2009-03-26 22:05:17 +00:00
|
|
|
vr->response.http_status = 404;
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-03-01 20:16:58 +00:00
|
|
|
case EACCES:
|
2009-03-17 13:21:20 +00:00
|
|
|
vr->response.http_status = 403;
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-03-01 20:16:58 +00:00
|
|
|
default:
|
2009-03-26 22:05:17 +00:00
|
|
|
VR_ERROR(vr, "stat() or open() for '%s' failed: %s", vr->physical.path->str, g_strerror(err));
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2009-03-17 13:21:20 +00:00
|
|
|
}
|
2009-03-26 22:05:17 +00:00
|
|
|
} else if (S_ISDIR(st.st_mode)) {
|
2009-03-26 22:33:28 +00:00
|
|
|
if (fd != -1)
|
2009-03-26 22:16:41 +00:00
|
|
|
close(fd);
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-03-26 22:05:17 +00:00
|
|
|
} else if (!S_ISREG(st.st_mode)) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
2009-03-17 13:21:20 +00:00
|
|
|
VR_DEBUG(vr, "not a regular file: '%s'", vr->physical.path->str);
|
2009-03-01 20:16:58 +00:00
|
|
|
}
|
2009-03-26 22:16:41 +00:00
|
|
|
|
2009-03-26 22:33:28 +00:00
|
|
|
if (fd != -1)
|
2009-03-26 22:16:41 +00:00
|
|
|
close(fd);
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
if (!li_vrequest_handle_direct(vr)) {
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2009-03-18 14:30:13 +00:00
|
|
|
}
|
2009-03-17 13:21:20 +00:00
|
|
|
vr->response.http_status = 403;
|
2008-08-09 15:20:12 +00:00
|
|
|
} else {
|
2009-10-07 20:49:40 +00:00
|
|
|
const GString *mime_str;
|
2009-03-17 13:21:20 +00:00
|
|
|
gboolean cachable;
|
2009-10-07 20:49:40 +00:00
|
|
|
gboolean ranged_response = FALSE;
|
|
|
|
liHttpHeader *hh_range;
|
|
|
|
liChunkFile *cf;
|
|
|
|
static const GString default_mime_str = { CONST_STR_LEN("application/octet-stream"), 0 };
|
|
|
|
|
2008-08-09 15:20:12 +00:00
|
|
|
#ifdef FD_CLOEXEC
|
|
|
|
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
|
|
|
#endif
|
2009-01-29 16:36:30 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
if (!li_vrequest_handle_direct(vr)) {
|
2008-09-08 00:28:55 +00:00
|
|
|
close(fd);
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2009-03-17 13:21:20 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_etag_set_header(vr, &st, &cachable);
|
2009-03-17 13:21:20 +00:00
|
|
|
if (cachable) {
|
|
|
|
vr->response.http_status = 304;
|
2009-03-18 03:12:51 +00:00
|
|
|
close(fd);
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2008-09-08 00:28:55 +00:00
|
|
|
}
|
2009-03-17 13:21:20 +00:00
|
|
|
|
2009-10-07 20:49:40 +00:00
|
|
|
cf = li_chunkfile_new(NULL, fd, FALSE);
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
mime_str = li_mimetype_get(vr, vr->physical.path);
|
2009-10-07 20:49:40 +00:00
|
|
|
if (!mime_str) mime_str = &default_mime_str;
|
|
|
|
|
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_STATIC_RANGE_REQUESTS).boolean) {
|
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
|
|
|
|
|
|
|
|
hh_range = li_http_header_lookup(vr->request.headers, CONST_STR_LEN("range"));
|
|
|
|
if (hh_range) {
|
|
|
|
/* TODO: Check If-Range: header */
|
2009-10-09 13:38:12 +00:00
|
|
|
const GString range_str = li_const_gstring(LI_HEADER_VALUE_LEN(hh_range));
|
2009-10-07 20:49:40 +00:00
|
|
|
liParseHttpRangeState rs;
|
|
|
|
gboolean is_multipart = FALSE, done = FALSE;
|
|
|
|
|
|
|
|
li_parse_http_range_init(&rs, &range_str, st.st_size);
|
|
|
|
do {
|
|
|
|
switch (li_parse_http_range_next(&rs)) {
|
|
|
|
case LI_PARSE_HTTP_RANGE_OK:
|
|
|
|
if (!is_multipart && !rs.last_range) {
|
|
|
|
is_multipart = TRUE;
|
|
|
|
}
|
2009-10-07 20:53:50 +00:00
|
|
|
g_string_printf(vr->wrk->tmp_str, "bytes %"G_GINT64_FORMAT"-%"G_GINT64_FORMAT"/%"G_GINT64_FORMAT, rs.range_start, rs.range_end, (goffset) st.st_size);
|
2009-10-07 20:49:40 +00:00
|
|
|
if (is_multipart) {
|
|
|
|
GString *subheader = g_string_sized_new(1023);
|
|
|
|
g_string_append_printf(subheader, "\r\n--%s\r\nContent-Type: %s\r\nContent-Range: %s\r\n\r\n", boundary, mime_str->str, vr->wrk->tmp_str->str);
|
|
|
|
li_chunkqueue_append_string(vr->out, subheader);
|
|
|
|
li_chunkqueue_append_chunkfile(vr->out, cf, rs.range_start, rs.range_length);
|
|
|
|
} else {
|
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Range"), GSTR_LEN(vr->wrk->tmp_str));
|
|
|
|
li_chunkqueue_append_chunkfile(vr->out, cf, rs.range_start, rs.range_length);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LI_PARSE_HTTP_RANGE_DONE:
|
|
|
|
ranged_response = TRUE;
|
|
|
|
done = TRUE;
|
|
|
|
vr->response.http_status = 206;
|
|
|
|
if (is_multipart) {
|
|
|
|
GString *subheader = g_string_sized_new(1023);
|
|
|
|
g_string_append_printf(subheader, "\r\n--%s--\r\n", boundary);
|
|
|
|
li_chunkqueue_append_string(vr->out, subheader);
|
|
|
|
|
|
|
|
g_string_printf(vr->wrk->tmp_str, "multipart/byteranges; boundary=%s", boundary);
|
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), GSTR_LEN(vr->wrk->tmp_str));
|
|
|
|
} else {
|
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), GSTR_LEN(mime_str));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LI_PARSE_HTTP_RANGE_INVALID:
|
|
|
|
done = TRUE;
|
|
|
|
li_chunkqueue_reset(vr->out);
|
|
|
|
break;
|
|
|
|
case LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE:
|
|
|
|
ranged_response = TRUE;
|
|
|
|
done = TRUE;
|
|
|
|
li_chunkqueue_reset(vr->out); vr->out->is_closed = TRUE;
|
2009-10-07 20:53:50 +00:00
|
|
|
g_string_printf(vr->wrk->tmp_str, "bytes */%"G_GINT64_FORMAT, (goffset) st.st_size);
|
2009-10-07 20:49:40 +00:00
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Range"), GSTR_LEN(vr->wrk->tmp_str));
|
|
|
|
vr->response.http_status = 416;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (!done);
|
|
|
|
li_parse_http_range_clear(&rs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ranged_response) {
|
|
|
|
vr->response.http_status = 200;
|
2009-07-09 20:17:24 +00:00
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), GSTR_LEN(mime_str));
|
2009-10-07 21:07:05 +00:00
|
|
|
li_chunkqueue_append_chunkfile(vr->out, cf, 0, st.st_size);
|
2009-10-07 20:49:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
li_chunkfile_release(cf);
|
2008-08-09 15:20:12 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2008-07-23 20:25:16 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_static(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2008-09-26 14:11:08 +00:00
|
|
|
if (val) {
|
2008-07-23 20:25:16 +00:00
|
|
|
ERROR(srv, "%s", "static action doesn't have parameters");
|
2008-07-24 11:25:40 +00:00
|
|
|
return NULL;
|
2008-07-23 20:25:16 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
return li_action_new_function(core_handle_static, NULL, NULL, NULL);
|
2008-07-23 20:25:16 +00:00
|
|
|
}
|
2008-07-23 20:19:23 +00:00
|
|
|
|
2009-04-16 15:02:53 +00:00
|
|
|
|
2009-11-11 13:55:00 +00:00
|
|
|
static liHandlerResult core_handle_pathinfo(liVRequest *vr, gpointer param, gpointer *context) {
|
|
|
|
struct stat st;
|
|
|
|
int err;
|
|
|
|
liHandlerResult res;
|
|
|
|
gchar *slash;
|
|
|
|
UNUSED(param);
|
|
|
|
UNUSED(context);
|
|
|
|
|
|
|
|
if (li_vrequest_is_handled(vr)) return LI_HANDLER_GO_ON;
|
|
|
|
|
|
|
|
next_round:
|
|
|
|
if (vr->physical.path->len <= vr->physical.doc_root->len) return LI_HANDLER_GO_ON;
|
|
|
|
|
2010-02-08 16:00:44 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "stat: physical path: %s", vr->physical.path->str);
|
|
|
|
}
|
2009-11-11 13:55:00 +00:00
|
|
|
res = li_stat_cache_get(vr, vr->physical.path, &st, &err, NULL);
|
2010-05-01 09:51:34 +00:00
|
|
|
if (res == LI_HANDLER_GO_ON) {
|
|
|
|
if (vr->physical.pathinfo->len > 0) {
|
|
|
|
/* remove PATHINFO from url too ("SCRIPT_NAME") */
|
|
|
|
if (li_string_suffix(vr->request.uri.path, GSTR_LEN(vr->physical.pathinfo))) {
|
|
|
|
g_string_set_size(vr->request.uri.path, vr->request.uri.path->len - vr->physical.pathinfo->len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-11-11 13:55:00 +00:00
|
|
|
if (res == LI_HANDLER_WAIT_FOR_EVENT || res == LI_HANDLER_GO_ON)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
/* stat failed. why? */
|
2010-02-08 16:00:44 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "stat failed %i: physical path: %s", err, vr->physical.path->str);
|
|
|
|
}
|
2009-11-11 13:55:00 +00:00
|
|
|
switch (err) {
|
|
|
|
case ENOTDIR:
|
|
|
|
slash = strrchr(vr->physical.path->str, '/');
|
|
|
|
if (!slash) {
|
2010-02-08 16:00:44 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "no slash: %s", vr->physical.path->str);
|
|
|
|
}
|
2009-11-11 13:55:00 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
g_string_prepend(vr->physical.pathinfo, slash);
|
|
|
|
g_string_set_size(vr->physical.path, slash - vr->physical.path->str);
|
2010-02-08 16:00:44 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "physical path: %s", vr->physical.path->str);
|
|
|
|
}
|
2009-11-11 13:55:00 +00:00
|
|
|
goto next_round;
|
|
|
|
case ENOENT:
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
case EACCES:
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
default:
|
|
|
|
VR_ERROR(vr, "stat() or open() for '%s' failed: %s", vr->physical.path->str, g_strerror(err));
|
|
|
|
return LI_HANDLER_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return LI_HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_pathinfo(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-11-11 13:55:00 +00:00
|
|
|
if (val) {
|
|
|
|
ERROR(srv, "%s", "pathinfo action doesn't have parameters");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return li_action_new_function(core_handle_pathinfo, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_status(liVRequest *vr, gpointer param, gpointer *context) {
|
2009-04-16 15:02:53 +00:00
|
|
|
UNUSED(param);
|
|
|
|
UNUSED(context);
|
|
|
|
|
|
|
|
vr->response.http_status = GPOINTER_TO_INT(param);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-04-16 15:02:53 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_status(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-04-16 15:02:53 +00:00
|
|
|
gpointer ptr;
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-04-16 15:02:53 +00:00
|
|
|
|
2009-07-16 10:57:11 +00:00
|
|
|
if (!val || val->type != LI_VALUE_NUMBER) {
|
2009-10-07 19:08:28 +00:00
|
|
|
ERROR(srv, "%s", "set_status action expects a number as parameter");
|
2009-04-16 15:02:53 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-24 13:00:29 +00:00
|
|
|
ptr = GINT_TO_POINTER((gint) val->data.number);
|
2009-04-16 15:02:53 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
return li_action_new_function(core_handle_status, NULL, NULL, ptr);
|
2009-04-16 15:02:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static void core_log_write_free(liServer *srv, gpointer param) {
|
2009-03-06 18:19:36 +00:00
|
|
|
UNUSED(srv);
|
|
|
|
g_string_free(param, TRUE);
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_log_write(liVRequest *vr, gpointer param, gpointer *context) {
|
2009-01-06 23:01:20 +00:00
|
|
|
GString *msg = param;
|
|
|
|
|
|
|
|
UNUSED(context);
|
|
|
|
|
|
|
|
VR_INFO(vr, "%s", msg->str);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2009-01-06 23:01:20 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_log_write(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2009-07-08 19:06:07 +00:00
|
|
|
if (!val || val->type != LI_VALUE_STRING) {
|
2009-01-06 23:01:20 +00:00
|
|
|
ERROR(srv, "%s", "log.write expects a string parameter");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-01-24 13:00:29 +00:00
|
|
|
return li_action_new_function(core_handle_log_write, NULL, core_log_write_free, li_value_extract_string(val));
|
2009-01-06 23:01:20 +00:00
|
|
|
}
|
|
|
|
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
static liHandlerResult core_handle_blank(liVRequest *vr, gpointer param, gpointer *context) {
|
2008-08-16 22:23:52 +00:00
|
|
|
UNUSED(param);
|
2008-12-09 23:23:27 +00:00
|
|
|
UNUSED(context);
|
2008-08-16 22:23:52 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
if (!li_vrequest_handle_direct(vr)) return LI_HANDLER_GO_ON;
|
2008-08-16 22:23:52 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
vr->response.http_status = 200;
|
2008-08-16 22:23:52 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2008-08-16 22:23:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-07 18:54:50 +00:00
|
|
|
static liAction* core_blank(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
|
|
|
|
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
|
2008-08-16 22:23:52 +00:00
|
|
|
|
2008-09-26 14:11:08 +00:00
|
|
|
if (val) {
|
2009-03-15 23:37:46 +00:00
|
|
|
ERROR(srv, "%s", "'blank' action doesn't have parameters");
|
2008-08-16 22:23:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
return li_action_new_function(core_handle_blank, NULL, NULL, NULL);
|
2008-08-16 22:23:52 +00:00
|
|
|
}
|
|
|
|
|
2008-10-17 16:08:40 +00:00
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
static gboolean core_listen(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
2008-09-27 15:06:43 +00:00
|
|
|
GString *ipstr;
|
2009-12-21 11:29:14 +00:00
|
|
|
UNUSED(p); UNUSED(userdata);
|
2008-09-27 15:06:43 +00:00
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_STRING) {
|
2008-07-23 20:19:23 +00:00
|
|
|
ERROR(srv, "%s", "listen expects a string as parameter");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2008-12-20 15:25:02 +00:00
|
|
|
ipstr = val->data.string;
|
2009-09-08 17:09:39 +00:00
|
|
|
li_angel_listen(srv, ipstr, NULL, NULL);
|
2008-12-20 15:25:02 +00:00
|
|
|
|
2008-07-23 20:19:23 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-13 17:57:19 +00:00
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
static gboolean core_workers(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
2008-09-09 09:31:08 +00:00
|
|
|
gint workers;
|
2009-12-21 11:29:14 +00:00
|
|
|
UNUSED(p); UNUSED(userdata);
|
2008-09-09 09:31:08 +00:00
|
|
|
|
2008-09-26 14:11:08 +00:00
|
|
|
workers = val->data.number;
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type != LI_VALUE_NUMBER || workers < 1) {
|
2008-09-09 09:31:08 +00:00
|
|
|
ERROR(srv, "%s", "workers expects a positive integer as parameter");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (srv->worker_count != 0) {
|
|
|
|
ERROR(srv, "workers already called with '%i', overwriting", srv->worker_count);
|
|
|
|
}
|
|
|
|
srv->worker_count = workers;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
static gboolean core_module_load(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) {
|
2009-07-09 20:17:24 +00:00
|
|
|
liValue *mods = li_value_new_list();
|
2009-10-04 14:58:31 +00:00
|
|
|
|
2009-12-21 11:29:14 +00:00
|
|
|
UNUSED(p); UNUSED(userdata);
|
2008-10-22 14:54:44 +00:00
|
|
|
|
|
|
|
if (!g_module_supported()) {
|
|
|
|
ERROR(srv, "%s", "module loading not supported on this platform");
|
2009-07-09 20:17:24 +00:00
|
|
|
li_value_free(mods);
|
2008-10-22 14:54:44 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
if (val->type == LI_VALUE_STRING) {
|
2008-10-22 14:54:44 +00:00
|
|
|
/* load only one module */
|
|