Пример #1
0
static void request_propfind_element(DavServer *server, DavRequest *request, GString *buffer, GString *url, GString *path, struct stat *st, GPtrArray *proplist) {
	GString *failed = g_string_sized_new(0), *prop = g_string_sized_new(512);
	guint i, l;

	g_string_append_len(buffer, CONST_STR_LEN("<D:response><D:href>"));
	g_string_append_len(buffer, GSTR_LEN(request->http_base));
	g_string_append_len(buffer, GSTR_LEN(url)); /* TODO: encode url */
	g_string_append_len(buffer, CONST_STR_LEN("</D:href><D:propstat><D:prop>"));

	for (i = 0, l = proplist->len; i < l; i += 2) {
		guint status;
		GString *prop_ns = g_ptr_array_index(proplist, i);
		GString *prop_name = g_ptr_array_index(proplist, i+1);

		g_string_truncate(prop, 0);
		status = dav_server_get_property(prop, server, request, path, st, prop_ns, prop_name);

		if (200 == status) {
			g_string_append_len(buffer, GSTR_LEN(prop));
		} else {
			g_string_append_len(failed, CONST_STR_LEN("<D:propstat><D:prop>"));
			if (GSTR_EQUAL(prop_ns, "DAV:")) {
				g_string_append_printf(failed, "<D:%s/>", prop_name->str);
			} else {
				g_string_append_printf(failed, "<R:%s xmlns:R=\"%s\"/>", prop_name->str, prop_ns->str);
			}
			g_string_append_printf(failed, "</D:prop><D:status>HTTP/1.1 %i %s</D:status></D:propstat>", status, dav_response_status_str(status));
		}
	}
	g_string_append_len(buffer, CONST_STR_LEN("</D:prop><D:status>" STATUS_LINE_200 "</D:status></D:propstat>"));
	g_string_append_len(buffer, GSTR_LEN(failed));
	g_string_append_len(buffer, CONST_STR_LEN("</D:response>\n"));
}
Пример #2
0
static void request_del(DavServer *server, DavRequest *request) {
	GString *physpath = g_string_sized_new(0);
	GString *buffer = dav_response_prepare_buffer(server, request, 0);
	GString *failed = g_string_sized_new(0);
	guint rawbufsize, oldbufsize;

	/* Depth must be unspecified or infinity for directories - we don't check it */

	dav_server_map_path(physpath, server, request->url_path);

	g_string_append_len(buffer, GSTR_LEN(&XML_Start));
	g_string_append_len(buffer, GSTR_LEN(&MultiStatus_Start));

	rawbufsize = buffer->len;
	g_string_append_len(buffer, CONST_STR_LEN("<D:response>"));
	oldbufsize = buffer->len;

	request_del_recurse(server, request, request->url_path, physpath, buffer, failed);

	/* TODO: del db properties */

	if (oldbufsize == buffer->len) {
		g_string_truncate(buffer, rawbufsize);
	} else {
		g_string_append_len(buffer, CONST_STR_LEN("<D:status>" STATUS_LINE_200 "</D:status></D:response>"));
	}

	g_string_append_len(buffer, GSTR_LEN(failed));

	g_string_append_len(buffer, GSTR_LEN(&MultiStatus_End));
	dav_response_xml_header(server, request);
	request->response_status = 207;
}
Пример #3
0
static liHandlerResult expire(liVRequest *vr, gpointer param, gpointer *context) {
	struct tm tm;
	time_t expire_date;
	guint len;
	gint max_age;
	GString *date_str = vr->wrk->tmp_str;
	expire_rule *rule = param;
	guint num = rule->num;
	time_t now = (time_t)li_cur_ts(vr->wrk);

	UNUSED(context);

	if (rule->base == EXPIRE_ACCESS) {
		expire_date = now + num;
		max_age = num;
	} else {
		/* modification */
		struct stat st;
		gint err;

		if (!vr->physical.path->len)
			return LI_HANDLER_GO_ON;

		switch (li_stat_cache_get(vr, vr->physical.path, &st, &err, NULL)) {
		case LI_HANDLER_GO_ON: break;
		case LI_HANDLER_WAIT_FOR_EVENT: return LI_HANDLER_WAIT_FOR_EVENT;
		default: return LI_HANDLER_GO_ON;
		}

		expire_date = st.st_mtime + num;

		if (expire_date < now)
			expire_date = now;

		max_age = expire_date - now;
	}

	/* format date */
	g_string_set_size(date_str, 255);

	if (!gmtime_r(&expire_date, &tm)) {
		VR_ERROR(vr, "gmtime_r(%"G_GUINT64_FORMAT") failed: %s", (guint64)expire_date, g_strerror(errno));
		return LI_HANDLER_GO_ON;
	}

	len = strftime(date_str->str, date_str->allocated_len, "%a, %d %b %Y %H:%M:%S GMT", &tm);
	if (len == 0)
		return LI_HANDLER_GO_ON;

	g_string_set_size(date_str, len);

	/* finally set the headers */
	li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Expires"), GSTR_LEN(date_str));
	g_string_truncate(date_str, 0);
	g_string_append_len(date_str, CONST_STR_LEN("max-age="));
	li_string_append_int(date_str, max_age);
	li_http_header_append(vr->response.headers, CONST_STR_LEN("Cache-Control"), GSTR_LEN(date_str));

	return LI_HANDLER_GO_ON;
}
Пример #4
0
static void request_propfind(DavServer *server, DavRequest *request) {
	GString *buffer;
	GString *physpath = g_string_sized_new(0);
	struct stat st;
	gboolean allprops, nameprops;
	GPtrArray *proplist = NULL;
	dav_walk walkctx;

	if (!dav_xml_parse_propfind(server, request, &allprops, &nameprops, &proplist)) goto cleanup;

	dav_server_map_path(physpath, server, request->url_path);

	if (-1 == stat(physpath->str, &st)) {
		switch (errno) {
		case EACCES:
			dav_response_error(server, request, 403);
			goto cleanup;
		case ENOENT:
		case ENOTDIR:
			dav_response_error(server, request, 404);
			goto cleanup;
		default:
			dav_response_error(server, request, 500);
			/* TODO: log error */
			goto cleanup;
		}
	}

	buffer = dav_response_prepare_buffer(server, request, 0);

	if (S_ISDIR(st.st_mode) && '/' != request->url_path->str[request->url_path->len-1]) {
		dav_append_trailing_slash(request->url_path);
		dav_response_location(server, request, request->url_path);
	}

	request->response_status = 207;
	g_string_append_len(buffer, GSTR_LEN(&XML_Start));
	g_string_append_len(buffer, GSTR_LEN(&MultiStatus_Start));

	dav_walk_init(server, request, &walkctx, physpath, request->url_path, &st);

	while (dav_walk_next(server, request, &walkctx, request->depth)) {
		if (allprops) {
			request_propfind_element_allprops(server, request, buffer, walkctx.currenturl, walkctx.currentpath, &walkctx.st);
		} else if (nameprops) {
			request_propfind_element_nameprops(server, request, buffer, walkctx.currenturl, walkctx.currentpath, &walkctx.st);
		} else {
			request_propfind_element(server, request, buffer, walkctx.currenturl, walkctx.currentpath, &walkctx.st, proplist);
		}
	}

	dav_walk_clear(server, request, &walkctx);

	g_string_append_len(buffer, GSTR_LEN(&MultiStatus_End));
	dav_response_xml_header(server, request);

cleanup:
	if (NULL != proplist) g_ptr_array_free(proplist, TRUE);
	g_string_free(physpath, TRUE);
}
Пример #5
0
static gboolean lua_find_file(GString *filename) {
	gboolean res = TRUE;
	struct stat st;

	if (-1 == stat(filename->str, &st) || !S_ISREG(st.st_mode)) {
		GString *tmp;

		if (filename->str[0] == '/') return FALSE;

		tmp = g_string_sized_new(0);

		/* try DEFAULT_LUADIR */
		li_string_assign_len(tmp, CONST_STR_LEN(DEFAULT_LUADIR "/"));
		g_string_append_len(tmp, GSTR_LEN(filename));
		if (-1 != stat(tmp->str, &st) && S_ISREG(st.st_mode)) {
			li_string_assign_len(filename, GSTR_LEN(tmp));
		} else {
			res = FALSE;
		}

		g_string_free(tmp, TRUE);
	}

	return res;
}
Пример #6
0
static void request_propfind_element_nameprops(DavServer *server, DavRequest *request, GString *buffer, GString *url, GString *path, struct stat *st) {
	g_string_append_len(buffer, CONST_STR_LEN("<D:response><D:href>"));
	g_string_append_len(buffer, GSTR_LEN(request->http_base));
	g_string_append_len(buffer, GSTR_LEN(url)); /* TODO: encode url */
	g_string_append_len(buffer, CONST_STR_LEN("</D:href><D:propstat><D:prop>"));
	dav_server_name_properties(buffer, server, request, path, st);
	g_string_append_len(buffer, CONST_STR_LEN("</D:prop><D:status>" STATUS_LINE_200 "</D:status></D:propstat></D:response>\n"));
}
Пример #7
0
int li_lua_push_value(lua_State *L, liValue *value) {
	if (NULL == value) {
		lua_pushnil(L);
		return 1;
	}

	switch (value->type) {
	case LI_VALUE_NONE:
		lua_pushnil(L);
		break;
	case LI_VALUE_BOOLEAN:
		lua_pushboolean(L, value->data.boolean);
		break;
	case LI_VALUE_NUMBER:
		lua_pushinteger(L, value->data.number);
		break;
	case LI_VALUE_STRING:
		lua_pushlstring(L, GSTR_LEN(value->data.string));
		break;
	case LI_VALUE_LIST: {
		lua_newtable(L);
		LI_VALUE_FOREACH(entry, value)
			li_lua_push_value(L, entry);
			lua_rawseti(L, -2, _entry_i + 1);
		LI_VALUE_END_FOREACH()
		/* kvlist lookup for string/nil keys */
		lua_push_kvlist_metatable(L);
		lua_setmetatable(L, -2);
	} break;
	case LI_VALUE_HASH: {
		GHashTableIter it;
		gpointer pkey, pvalue;
		lua_newtable(L);

		g_hash_table_iter_init(&it, value->data.hash);
		while (g_hash_table_iter_next(&it, &pkey, &pvalue)) {
			GString *key = pkey;
			liValue *subval = pvalue;
			lua_pushlstring(L, GSTR_LEN(key));
			li_lua_push_value(L, subval);
			lua_rawset(L, -3);
		}
	} break;
	case LI_VALUE_ACTION:
		li_action_acquire(value->data.val_action.action);
		li_lua_push_action(value->data.val_action.srv, L, value->data.val_action.action);
		break;
	case LI_VALUE_CONDITION:
		li_condition_acquire(value->data.val_cond.cond);
		li_lua_push_condition(value->data.val_cond.srv, L, value->data.val_cond.cond);
		break;
	default: /* ignore error and push nil */
		lua_pushnil(L);
		break;
	}
	return 1;
}
Пример #8
0
int li_lua_push_value(lua_State *L, liValue *value) {
	if (NULL == value) {
		lua_pushnil(L);
		return 1;
	}

	switch (value->type) {
	case LI_VALUE_NONE:
		lua_pushnil(L);
		break;
	case LI_VALUE_BOOLEAN:
		lua_pushboolean(L, value->data.boolean);
		break;
	case LI_VALUE_NUMBER:
		lua_pushinteger(L, value->data.number);
		break;
	case LI_VALUE_STRING:
		lua_pushlstring(L, GSTR_LEN(value->data.string));
		break;
	case LI_VALUE_LIST: {
		GArray *list = value->data.list;
		guint i;
		lua_newtable(L);
		for (i = 0; i < list->len; i++) {
			liValue *subval = g_array_index(list, liValue*, i);
			li_lua_push_value(L, subval);
			lua_rawseti(L, -2, i);
		}
	} break;
	case LI_VALUE_HASH: {
		GHashTableIter it;
		gpointer pkey, pvalue;
		lua_newtable(L);

		g_hash_table_iter_init(&it, value->data.hash);
		while (g_hash_table_iter_next(&it, &pkey, &pvalue)) {
			GString *key = pkey;
			liValue *subval = pvalue;
			lua_pushlstring(L, GSTR_LEN(key));
			li_lua_push_value(L, subval);
			lua_rawset(L, -3);
		}
	} break;
	case LI_VALUE_ACTION:
		li_action_acquire(value->data.val_action.action);
		li_lua_push_action(value->data.val_action.srv, L, value->data.val_action.action);
		break;
	case LI_VALUE_CONDITION:
		li_condition_acquire(value->data.val_cond.cond);
		li_lua_push_condition(value->data.val_cond.srv, L, value->data.val_cond.cond);
		break;
	default: /* ignore error and push nil */
		lua_pushnil(L);
		break;
	}
	return 1;
}
Пример #9
0
static GString* createFileName(liVRequest *vr, GString *path, liHttpHeader *etagheader) {
	GString *file = g_string_sized_new(255);
	gchar* etag_base64 = g_base64_encode((guchar*) LI_HEADER_VALUE_LEN(etagheader));
	g_string_append_len(file, GSTR_LEN(path));
	g_string_append_len(file, GSTR_LEN(vr->request.uri.path));
	g_string_append_len(file, CONST_STR_LEN("-"));
	g_string_append(file, etag_base64);
	g_free(etag_base64);
	return file;
}
Пример #10
0
void li_request_copy(liRequest *dest, const liRequest *src) {
	GList *iter;

	dest->http_method = src->http_method;
	li_string_assign_len(dest->http_method_str, GSTR_LEN(src->http_method_str));
	dest->http_version = src->http_version;

	li_string_assign_len(dest->uri.raw, GSTR_LEN(src->uri.raw));
	li_string_assign_len(dest->uri.raw_path, GSTR_LEN(src->uri.raw_path));
	li_string_assign_len(dest->uri.raw_orig_path, GSTR_LEN(src->uri.raw_orig_path));
	li_string_assign_len(dest->uri.scheme, GSTR_LEN(src->uri.scheme));
	li_string_assign_len(dest->uri.authority, GSTR_LEN(src->uri.authority));
	li_string_assign_len(dest->uri.path, GSTR_LEN(src->uri.path));
	li_string_assign_len(dest->uri.query, GSTR_LEN(src->uri.query));
	li_string_assign_len(dest->uri.host, GSTR_LEN(src->uri.host));

	li_http_headers_reset(dest->headers);

	for (iter = g_queue_peek_head_link(&src->headers->entries); iter; iter = g_list_next(iter)) {
		liHttpHeader* header = (liHttpHeader*) iter->data;

		li_http_header_insert(dest->headers, LI_HEADER_KEY_LEN(header), LI_HEADER_VALUE_LEN(header));
	}

	dest->content_length = src->content_length;
}
Пример #11
0
static void proxy_send_headers(liVRequest *vr, proxy_connection *pcon) {
	GString *head = g_string_sized_new(4095);
	liHttpHeader *header;
	GList *iter;
	gchar *enc_path;

	g_string_append_len(head, GSTR_LEN(vr->request.http_method_str));
	g_string_append_len(head, CONST_STR_LEN(" "));

	enc_path = g_uri_escape_string(vr->request.uri.path->str, "/", FALSE);
	g_string_append(head, enc_path);
	g_free(enc_path);

	if (vr->request.uri.query->len > 0) {
		g_string_append_len(head, CONST_STR_LEN("?"));
		g_string_append_len(head, GSTR_LEN(vr->request.uri.query));
	}

	switch (vr->request.http_version) {
	case LI_HTTP_VERSION_1_1:
		/* g_string_append_len(head, CONST_STR_LEN(" HTTP/1.1\r\n")); */
		g_string_append_len(head, CONST_STR_LEN(" HTTP/1.0\r\n"));
		break;
	case LI_HTTP_VERSION_1_0:
	default:
		g_string_append_len(head, CONST_STR_LEN(" HTTP/1.0\r\n"));
		break;
	}

	for (iter = g_queue_peek_head_link(&vr->request.headers->entries); iter; iter = g_list_next(iter)) {
		header = (liHttpHeader*) iter->data;
		if (li_http_header_key_is(header, CONST_STR_LEN("Connection"))) continue;
		if (li_http_header_key_is(header, CONST_STR_LEN("Proxy-Connection"))) continue;
		if (li_http_header_key_is(header, CONST_STR_LEN("X-Forwarded-Proto"))) continue;
		g_string_append_len(head, GSTR_LEN(header->data));
		g_string_append_len(head, CONST_STR_LEN("\r\n"));
	}

	g_string_append_len(head, CONST_STR_LEN("X-Forwarded-For: "));
	g_string_append_len(head, GSTR_LEN(vr->coninfo->remote_addr_str));
	g_string_append_len(head, CONST_STR_LEN("\r\n"));

	if (vr->coninfo->is_ssl) {
		g_string_append_len(head, CONST_STR_LEN("X-Forwarded-Proto: https\r\n"));
	} else {
		g_string_append_len(head, CONST_STR_LEN("X-Forwarded-Proto: http\r\n"));
	}

	/* terminate http header */
	g_string_append_len(head, CONST_STR_LEN("\r\n"));

	li_chunkqueue_append_string(pcon->proxy_out, head);
}
Пример #12
0
void dav_server_map_path(GString *physpath, DavServer *server, GString *urlpath) {
	dav_path_simplify(urlpath);

	g_string_truncate(physpath, 0);
	g_string_append_len(physpath, GSTR_LEN(server->docroot));
	g_string_append_len(physpath, GSTR_LEN(urlpath));

	/* remove trailing slash(es) */
	while (physpath->len > 1 && '/' == physpath->str[physpath->len-1]) {
		physpath->str[--physpath->len] = '\0';
	}
}
Пример #13
0
static proxy_context* proxy_context_new(liServer *srv, GString *dest_socket) {
	liSocketAddress saddr;
	proxy_context* ctx;
	liBackendConfig *config;

	saddr = li_sockaddr_from_string(dest_socket, 0);
	if (NULL == saddr.addr) {
		ERROR(srv, "Invalid socket address '%s'", dest_socket->str);
		return NULL;
	}

	config = g_slice_new0(liBackendConfig);
	config->callbacks = &proxy_backend_cbs;
	config->sock_addr = saddr;
	config->max_connections = 0;
	config->idle_timeout = 5;
	config->connect_timeout = 5;
	config->wait_timeout = 5;
	config->disable_time = 0;
	config->max_requests = 1;
	config->watch_for_close = TRUE;

	ctx = g_slice_new0(proxy_context);
	ctx->refcount = 1;
	ctx->pool = li_backend_pool_new(config);
	ctx->socket_str = g_string_new_len(GSTR_LEN(dest_socket));

	return ctx;
}
Пример #14
0
static liHandlerResult redirect(liVRequest *vr, gpointer param, gpointer *context) {
	guint i;
	redirect_rule *rule;
	redirect_data *rd = param;
	gboolean debug = _OPTION(vr, rd->p, 0).boolean;
	GString *dest = vr->wrk->tmp_str;

	UNUSED(context);

	if (li_vrequest_is_handled(vr)) return LI_HANDLER_GO_ON;

	for (i = 0; i < rd->rules->len; i++) {
		rule = &g_array_index(rd->rules, redirect_rule, i);

		if (redirect_internal(vr, dest, rule)) {
			/* regex matched */
			if (debug) {
				VR_DEBUG(vr, "redirect: \"%s\"", dest->str);
			}

			if (!li_vrequest_handle_direct(vr)) return LI_HANDLER_ERROR;

			vr->response.http_status = 301;
			li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Location"), GSTR_LEN(dest));

			/* stop at first matching regex */
			return LI_HANDLER_GO_ON;
		}
	}

	return LI_HANDLER_GO_ON;
}
Пример #15
0
liMemcachedRequest* li_memcached_get(liMemcachedCon *con, GString *key, liMemcachedCB callback, gpointer cb_data, GError **err) {
	int_request* req;

	if (!li_memcached_is_key_valid(key)) {
		g_set_error(err, LI_MEMCACHED_ERROR, LI_MEMCACHED_BAD_KEY, "Invalid key: '%s'", key->str);
		return NULL;
	}

	if (-1 == con->fd) memcached_connect(con);
	if (-1 == con->fd) {
		if (NULL == con->err) {
			g_set_error(err, LI_MEMCACHED_ERROR, LI_MEMCACHED_DISABLED, "Not connected");
		} else if (err) {
			*err = g_error_copy(con->err);
		}
		return NULL;
	}

	req = g_slice_new0(int_request);
	req->req.callback = callback;
	req->req.cb_data = cb_data;

	req->type = REQ_GET;
	req->key = g_string_new_len(GSTR_LEN(key));

	if (!push_request(con, req, err)) {
		free_request(con, req);
		return NULL;
	}

	return &req->req;
}
Пример #16
0
static void fastcgi_env_add(GByteArray *buf, liEnvironmentDup *envdup, const gchar *key, size_t keylen, const gchar *val, size_t valuelen) {
	GString *sval;

	if (NULL != (sval = li_environment_dup_pop(envdup, key, keylen))) {
		append_key_value_pair(buf, key, keylen, GSTR_LEN(sval));
	} else {
		append_key_value_pair(buf, key, keylen, val, valuelen);
	}
}
Пример #17
0
liValue* li_value_copy(liValue* val) {
    liValue *n;
    if (NULL == val) return NULL;

    switch (val->type) {
    case LI_VALUE_NONE:
        return li_value_new_none();
    case LI_VALUE_BOOLEAN:
        return li_value_new_bool(val->data.boolean);
    case LI_VALUE_NUMBER:
        return li_value_new_number(val->data.number);
    case LI_VALUE_STRING:
        return li_value_new_string(g_string_new_len(GSTR_LEN(val->data.string)));
    /* list: we have to copy every value in the list! */
    case LI_VALUE_LIST:
        n = li_value_new_list();
        g_array_set_size(n->data.list, val->data.list->len);
        for (guint i = 0; i < val->data.list->len; i++) {
            g_array_index(n->data.list, liValue*, i) = li_value_copy(g_array_index(val->data.list, liValue*, i));
        }
        return n;
    /* hash: iterate over hashtable, clone each value */
    case LI_VALUE_HASH:
        n = li_value_new_hash();
        {
            GHashTableIter iter;
            gpointer k, v;
            g_hash_table_iter_init(&iter, val->data.hash);
            while (g_hash_table_iter_next(&iter, &k, &v))
                g_hash_table_insert(n->data.hash, g_string_new_len(GSTR_LEN((GString*)k)), li_value_copy((liValue*)v));
        }
        return n;
    case LI_VALUE_ACTION:
        li_action_acquire(val->data.val_action.action);
        n = li_value_new_action(val->data.val_action.srv, val->data.val_action.action);
        return n;
    case LI_VALUE_CONDITION:
        li_condition_acquire(val->data.val_cond.cond);
        n = li_value_new_condition(val->data.val_cond.srv, val->data.val_cond.cond);
        return n;
    }
    return NULL;
}
Пример #18
0
void li_memcached_mutate_key(GString *key) {
	GChecksum *hash;

	if (li_memcached_is_key_valid(key)) return;

	hash = g_checksum_new(G_CHECKSUM_SHA1);

	g_checksum_update(hash, (const guchar *) GSTR_LEN(key));
	g_string_assign(key, g_checksum_get_string(hash));

	g_checksum_free(hash);
}
Пример #19
0
liChunkFile *li_chunkfile_new(GString *name, int fd, gboolean is_temp) {
	liChunkFile *cf = g_slice_new(liChunkFile);
	cf->refcount = 1;
	if (name) {
		cf->name = g_string_new_len(GSTR_LEN(name));
	} else {
		cf->name = NULL;
	}
	cf->fd = fd;
	cf->is_temp = is_temp;
	return cf;
}
Пример #20
0
static void fastcgi_send_env(liVRequest *vr, fastcgi_connection *fcon) {
	GByteArray *buf = g_byte_array_sized_new(0);
	liEnvironmentDup *envdup;

	envdup = li_environment_make_dup(&vr->env);
	fastcgi_env_create(vr, envdup, buf);

	{
		GList *i;
		GString *tmp = vr->wrk->tmp_str;

		for (i = vr->request.headers->entries.head; NULL != i; i = i->next) {
			liHttpHeader *h = (liHttpHeader*) i->data;
			const GString hkey = li_const_gstring(h->data->str, h->keylen);
			g_string_truncate(tmp, 0);
			if (!li_strncase_equal(&hkey, CONST_STR_LEN("CONTENT-TYPE"))) {
				g_string_append_len(tmp, CONST_STR_LEN("HTTP_"));
			}
			g_string_append_len(tmp, h->data->str, h->keylen);
			fix_header_name(tmp);
	
			fastcgi_env_add(buf, envdup, GSTR_LEN(tmp), h->data->str + h->keylen+2, h->data->len - (h->keylen+2));
		}
	}

	{
		GHashTableIter i;
		gpointer key, val;

		g_hash_table_iter_init(&i, envdup->table);
		while (g_hash_table_iter_next(&i, &key, &val)) {
			append_key_value_pair(buf, GSTR_LEN((GString*) key), GSTR_LEN((GString*) val));
		}
	}

	li_environment_dup_free(envdup);

	stream_send_bytearr(fcon->fcgi_out, FCGI_PARAMS, fcon->requestid, buf);
	stream_send_fcgi_record(fcon->fcgi_out, FCGI_PARAMS, fcon->requestid, 0);
}
Пример #21
0
gboolean li_angel_data_write_str  (GString *buf, const GString *str, GError **err) {
	g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
	if (str->len > LI_ANGEL_DATA_MAX_STR_LEN) {
		g_set_error(err,
			LI_ANGEL_DATA_ERROR,
			LI_ANGEL_DATA_ERROR_STRING_TOO_LONG,
			"String too long (len: %" G_GSIZE_FORMAT "): '%s'", str->len, str->str);
		return FALSE;
	}
	if (!li_angel_data_write_int32(buf, str->len, err)) return FALSE;
	g_string_append_len(buf, GSTR_LEN(str));
	return TRUE;
}
Пример #22
0
static liStatCacheEntry *stat_cache_entry_new(liStatCache *sc, GString *path) {
    liStatCacheEntry *sce;

    sce = g_slice_new0(liStatCacheEntry);
    sce->sc = sc;
    sce->data.path = g_string_new_len(GSTR_LEN(path));
    sce->vrequests = g_ptr_array_sized_new(8);
    sce->state = STAT_CACHE_ENTRY_WAITING;
    sce->queue_elem.data = sce;
    sce->refcount = 1;
    sce->cached = TRUE;

    return sce;
}
Пример #23
0
static void openssl_setenv_X509_add_PEM(liVRequest *vr, X509 *x509, const gchar *key, guint key_len) {
	gint n;
	GString *v = vr->wrk->tmp_str;

	BIO *bio;
	if (NULL != (bio = BIO_new(BIO_s_mem()))) {
		PEM_write_bio_X509(bio, x509);
		n = BIO_pending(bio);
		g_string_set_size(v, n);
		BIO_read(bio, v->str, n);
		BIO_free(bio);
		li_environment_set(&vr->env, key, key_len, GSTR_LEN(v));
	}
}
Пример #24
0
/** uses/modifies wrk->tmp_str */
static void try_append_file(liVRequest *vr, GString **curbuf, const gchar *filename, gboolean encode_html) {
	GString *f = vr->wrk->tmp_str;
	g_string_truncate(f, 0);
	g_string_append_len(f, GSTR_LEN(vr->physical.path));
	li_path_append_slash(f);
	g_string_append(f, filename);

	if (!encode_html) {
		int fd;
		struct stat st;

		while (-1 == (fd = open(f->str, O_RDONLY))) {
			if (errno == EINTR)
				continue;
			return; /* failed to open, ignore */
		}
		if (-1 == fstat(fd, &st)) {
			close(fd);
			return; /* failed to open, ignore */
		}
		if (st.st_size > MAX_INCLUDE_FILE_SIZE) {
			close(fd);
			return; /* file too big, ignore */
		}

		/* flush current buffer and append file */
		li_chunkqueue_append_string(vr->direct_out, *curbuf);
		*curbuf = g_string_sized_new(4*1024-1);
		li_chunkqueue_append_file_fd(vr->direct_out, NULL, 0, st.st_size, fd);
	} else {
		GError *error = NULL;
		gchar *contents;
		gsize length;

		if (!g_file_get_contents(f->str, &contents, &length, &error)) {
			g_error_free(error);
			return; /* ignore errors */
		}
		if (length > MAX_INCLUDE_FILE_SIZE) {
			g_free(contents);
			return; /* file too big, ignore */
		}

		g_string_append_len(*curbuf, CONST_STR_LEN("<pre>"));
		li_string_encode_append(contents, *curbuf, LI_ENCODING_HTML);
		g_string_append_len(*curbuf, CONST_STR_LEN("</pre>"));
		g_free(contents);
	}
}
Пример #25
0
void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatternCB nth_callback, gpointer nth_data, liPatternCB nth_prev_callback, gpointer nth_prev_data) {
	guint i;
	gboolean encoded;
	liHandlerResult res;
	liConditionValue cond_val;
	GArray *arr = (GArray*) pattern;
	GString *tmpstr = NULL;

	for (i = 0; i < arr->len; i++) {
		liPatternPart *part = &g_array_index(arr, liPatternPart, i);
		encoded = FALSE;

		switch (part->type) {
		case PATTERN_STRING:
			g_string_append_len(dest, GSTR_LEN(part->data.str));
			break;
		case PATTERN_NTH:
			if (NULL != nth_callback) {
				nth_callback(dest, part->data.range.from, part->data.range.to, nth_data);
			}
			break;
		case PATTERN_NTH_PREV:
			if (NULL != nth_prev_callback) {
				nth_prev_callback(dest, part->data.range.from, part->data.range.to, nth_prev_data);
			}
			break;
		case PATTERN_VAR_ENCODED:
			encoded = TRUE;
			/* fall through */
		case PATTERN_VAR:
			if (vr == NULL) continue;

			if (NULL == tmpstr) tmpstr = g_string_sized_new(127);

			res = li_condition_get_value(tmpstr, vr, part->data.lvalue, &cond_val, LI_COND_VALUE_HINT_STRING);
			if (res == LI_HANDLER_GO_ON) {
				if (encoded) {
					li_string_encode_append(li_condition_value_to_string(tmpstr, &cond_val), dest, LI_ENCODING_URI);
				} else {
					g_string_append(dest, li_condition_value_to_string(tmpstr, &cond_val));
				}
			}

			break;
		}
	}

	if (NULL != tmpstr) g_string_free(tmpstr, TRUE);
}
Пример #26
0
static AuthFile* auth_file_new(liWorker *wrk, const GString *path, gboolean has_realm, gint ttl) {
	AuthFile* f = g_slice_new0(AuthFile);
	f->path = g_string_new_len(GSTR_LEN(path));
	f->has_realm = has_realm;
	f->ttl = ttl;
	f->next_check = ev_now(wrk->loop) + ttl;
	f->lock = g_mutex_new();

	if (NULL == (f->data = auth_file_load(wrk->srv, f))) {
		auth_file_free(f);
		return NULL;
	}

	return f;
}
Пример #27
0
void li_pattern_array_cb(GString *pattern_result, guint from, guint to, gpointer data) {
	GArray *a = data;
	guint i;

	if (NULL == a || 0 == a->len) return;

	if (G_LIKELY(from <= to)) {
		to = MIN(to, a->len - 1);
		for (i = from; i <= to; i++) {
			GString *str = g_array_index(a, GString*, i);
			if (NULL != str) {
				g_string_append_len(pattern_result, GSTR_LEN(str));
			}
		}
	} else {
Пример #28
0
static proxy_context* proxy_context_new(liServer *srv, liPlugin *p, GString *dest_socket) {
	liSocketAddress saddr;
	proxy_context* ctx;
	saddr = li_sockaddr_from_string(dest_socket, 80);
	if (NULL == saddr.addr) {
		ERROR(srv, "Invalid socket address '%s'", dest_socket->str);
		return NULL;
	}
	ctx = g_slice_new0(proxy_context);
	ctx->refcount = 1;
	ctx->socket = saddr;
	ctx->timeout = 5;
	ctx->plugin = p;
	ctx->socket_str = g_string_new_len(GSTR_LEN(dest_socket));
	return ctx;
}
Пример #29
0
static gboolean cache_etag_file_start(liVRequest *vr, cache_etag_file *cfile) {
	cfile->tmpfilename = g_string_sized_new(cfile->filename->len + 7);
	g_string_append_len(cfile->tmpfilename, GSTR_LEN(cfile->filename));
	g_string_append_len(cfile->tmpfilename, CONST_STR_LEN("-XXXXXX"));

	if (!mkdir_for_file(vr, cfile->tmpfilename->str)) {
		return FALSE;
	}

	errno = 0; /* posix doesn't define any errors */
	if (-1 == (cfile->fd = mkstemp(cfile->tmpfilename->str))) {
		VR_ERROR(vr, "Couldn't create cache tempfile '%s': %s", cfile->tmpfilename->str, g_strerror(errno));
		return FALSE;
	}
#ifdef FD_CLOEXEC
	fcntl(cfile->fd, F_SETFD, FD_CLOEXEC);
#endif
	return TRUE;
}
Пример #30
0
void li_log_write(liServer *srv, liLogLevel log_level, guint flags, const gchar *fmt, ...) {
	va_list ap;
	GString *log_line = srv->log.log_line;

	if (!srv->log.levels[log_level]) return;

	g_string_truncate(log_line, 0);

	/* for normal error messages, we prepend a timestamp */
	if (flags & LI_LOG_FLAG_TIMESTAMP) {
		GString *log_ts = srv->log.ts_cache;
		time_t cur_ts;

		cur_ts = (time_t)ev_now(srv->loop);

		if (cur_ts != srv->log.last_ts) {
			gsize s;
			struct tm tm;

			g_string_set_size(log_ts, 255);
#ifdef HAVE_LOCALTIME_R
			s = strftime(log_ts->str, log_ts->allocated_len, "%Y-%m-%d %H:%M:%S %Z: ", localtime_r(&cur_ts, &tm));
#else
			s = strftime(log_ts->str, log_ts->allocated_len, "%Y-%m-%d %H:%M:%S %Z: ", localtime(&cur_ts));
#endif

			g_string_set_size(log_ts, s);

			srv->log.last_ts = cur_ts;
		}

		g_string_append_len(log_line, GSTR_LEN(log_ts));
	}

	va_start(ap, fmt);
	g_string_append_vprintf(log_line, fmt, ap);
	va_end(ap);

	g_string_append_len(log_line, CONST_STR_LEN("\n"));

	fprintf(stderr, "%s", log_line->str);
}