示例#1
0
/* st, res, errno, msg = vr:stat(filename)
 *  st: stat data (nil if not available (yet))
 *  res: error code (HANDLE_GO_ON if successful)
 *  errno: errno returned by stat() (only for HANDLER_ERROR)
 *  msg: error message for errno
 */
static int lua_vrequest_stat(lua_State *L) {
	liVRequest *vr;
	GString path;
	const char *filename;
	size_t filename_len;
	liHandlerResult res;
	int err = 0;
	struct stat st;

	if (lua_gettop(L) != 2) {
		lua_pushstring(L, "vr:stat(filename): incorrect number of arguments");
		lua_error(L);
	}

	vr = li_lua_get_vrequest(L, 1);
	if (!vr || !lua_isstring(L, 2)) {
		lua_pushstring(L, "vr:stat(filename): wrong argument types");
		lua_error(L);
	}

	filename = lua_tolstring(L, 2, &filename_len);
	path = li_const_gstring(filename, filename_len);

	res = li_stat_cache_get(vr, &path, &st, &err, NULL);
	switch (res) {
	case LI_HANDLER_GO_ON:
		li_lua_push_stat(L, &st);
		lua_pushinteger(L, res);
		return 2;
	case LI_HANDLER_WAIT_FOR_EVENT:
		lua_pushnil(L);
		lua_pushinteger(L, res);
		return 2;
	case LI_HANDLER_ERROR:
		lua_pushnil(L);
		lua_pushinteger(L, res);
		lua_pushinteger(L, err);
		lua_pushstring(L, g_strerror(err));
		return 4;
	case LI_HANDLER_COMEBACK:
		VR_ERROR(vr, "%s", "Unexpected return value from li_stat_cache_get: LI_HANDLER_COMEBACK");
		lua_pushnil(L);
		lua_pushinteger(L, LI_HANDLER_ERROR);
		return 2;
	}

	return 0;
}
示例#2
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);
}
示例#3
0
static memcached_ctx* mc_ctx_parse(liServer *srv, liPlugin *p, liValue *config) {
	memcached_ctx *ctx;
	memcached_config *mconf = p->data;
	GString def_server = li_const_gstring(CONST_STR_LEN("127.0.0.1:11211"));

	if (config && config->type != LI_VALUE_HASH) {
		ERROR(srv, "%s", "memcache expects an optional hash of options");
		return NULL;
	}

	ctx = g_slice_new0(memcached_ctx);
	ctx->srv = srv;
	ctx->refcount = 1;
	ctx->p = p;

	ctx->addr = li_sockaddr_from_string(&def_server, 11211);

	ctx->pattern = li_pattern_new(srv, "%{req.path}");

	ctx->flags = 0;
	ctx->ttl = 30;
	ctx->maxsize = 64*1024; /* 64 kB */
	ctx->headers = FALSE;

	if (config) {
		GHashTable *ht = config->data.hash;
		GHashTableIter it;
		gpointer pkey, pvalue;

		g_hash_table_iter_init(&it, ht);
		while (g_hash_table_iter_next(&it, &pkey, &pvalue)) {
			GString *key = pkey;
			liValue *value = pvalue;

			if (g_string_equal(key, &mon_server)) {
				if (value->type != LI_VALUE_STRING) {
					ERROR(srv, "memcache option '%s' expects string as parameter", mon_server.str);
					goto option_failed;
				}
				li_sockaddr_clear(&ctx->addr);
				ctx->addr = li_sockaddr_from_string(value->data.string, 11211);
				if (NULL == ctx->addr.addr) {
					ERROR(srv, "invalid socket address: '%s'", value->data.string->str);
					goto option_failed;
				}
			} else if (g_string_equal(key, &mon_key)) {
				if (value->type != LI_VALUE_STRING) {
					ERROR(srv, "memcache option '%s' expects string as parameter", mon_key.str);
					goto option_failed;
				}
				li_pattern_free(ctx->pattern);
				ctx->pattern = li_pattern_new(srv,  value->data.string->str);
				if (NULL == ctx->pattern) {
					ERROR(srv, "memcache: couldn't parse pattern for key '%s'", value->data.string->str);
					goto option_failed;
				}
			} else if (g_string_equal(key, &mon_flags)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number <= 0) {
					ERROR(srv, "memcache option '%s' expects positive integer as parameter", mon_flags.str);
					goto option_failed;
				}
				ctx->flags = value->data.number;
			} else if (g_string_equal(key, &mon_ttl)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number < 0) {
					ERROR(srv, "memcache option '%s' expects non-negative integer as parameter", mon_ttl.str);
					goto option_failed;
				}
				ctx->ttl = value->data.number;
			} else if (g_string_equal(key, &mon_maxsize)) {
				if (value->type != LI_VALUE_NUMBER || value->data.number <= 0) {
					ERROR(srv, "memcache option '%s' expects positive integer as parameter", mon_maxsize.str);
					goto option_failed;
				}
				ctx->maxsize = value->data.number;
			} else if (g_string_equal(key, &mon_headers)) {
				if (value->type != LI_VALUE_BOOLEAN) {
					ERROR(srv, "memcache option '%s' expects boolean as parameter", mon_headers.str);
					goto option_failed;
				}
				ctx->headers = value->data.boolean;
				if (ctx->headers) {
					ERROR(srv, "%s", "memcache: lookup/storing headers not supported yet");
					goto option_failed;
				}
			} else {
				ERROR(srv, "unknown option for memcache '%s'", key->str);
				goto option_failed;
			}
		}
	}

	if (LI_SERVER_INIT != g_atomic_int_get(&srv->state)) {
		ctx->worker_client_ctx = g_slice_alloc0(sizeof(liMemcachedCon*) * srv->worker_count);
	} else {
		ctx->mconf_link.data = ctx;
		g_queue_push_tail_link(&mconf->prepare_ctx, &ctx->mconf_link);
	}

	return ctx;

option_failed:
	mc_ctx_release(NULL, ctx);
	return NULL;
}
示例#4
0
static liHandlerResult auth_basic(liVRequest *vr, gpointer param, gpointer *context) {
	liHttpHeader *hdr;
	gboolean auth_ok = FALSE;
	AuthBasicData *bdata = param;
	gboolean debug = _OPTION(vr, bdata->p, 0).boolean;

	UNUSED(context);

	if (li_vrequest_is_handled(vr)) {
		if (debug || CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
			VR_DEBUG(vr, "skipping auth.basic as request is already handled with current status %i", vr->response.http_status);
		}
		return LI_HANDLER_GO_ON;
	}

	/* check for Authorization header */
	hdr = li_http_header_lookup(vr->request.headers, CONST_STR_LEN("Authorization"));

	if (!hdr || !g_str_has_prefix(LI_HEADER_VALUE(hdr), "Basic ")) {
		if (debug) {
			VR_DEBUG(vr, "requesting authorization from client for realm \"%s\"", bdata->realm->str);
		}
	} else {
		gchar *decoded, *username = NULL, *password;
		size_t len;
		/* auth_info contains username:password encoded in base64 */
		if (NULL != (decoded = (gchar*)g_base64_decode(LI_HEADER_VALUE(hdr) + sizeof("Basic ") - 1, &len))) {
			/* bogus data? */
			if (NULL != (password = strchr(decoded, ':'))) {
				*password = '******';
				password++;
				username = decoded;
			} else {
				g_free(decoded);
			}
		}

		if (!username) {
			if (debug) {
				VR_DEBUG(vr, "couldn't parse authorization info from client for realm \"%s\"", bdata->realm->str);
			}
		} else {
			GString user = li_const_gstring(username, password - username - 1);
			GString pass = li_const_gstring(password, len - (password - username));
			if (bdata->backend(vr, &user, &pass, bdata, debug)) {
				auth_ok = TRUE;

				li_environment_set(&vr->env, CONST_STR_LEN("REMOTE_USER"), username, password - username - 1);
				li_environment_set(&vr->env, CONST_STR_LEN("AUTH_TYPE"), CONST_STR_LEN("Basic"));
			} else {
				if (debug) {
					VR_DEBUG(vr, "wrong authorization info from client on realm \"%s\" (user: \"%s\")", bdata->realm->str, username);
				}
			}
			g_free(decoded);
		}
	}

	g_string_truncate(vr->wrk->tmp_str, 0);
	g_string_append_len(vr->wrk->tmp_str, CONST_STR_LEN("Basic realm=\""));
	g_string_append_len(vr->wrk->tmp_str, GSTR_LEN(bdata->realm));
	g_string_append_c(vr->wrk->tmp_str, '"');
	/* generate header always */

	if (!auth_ok) {
		li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("WWW-Authenticate"), GSTR_LEN(vr->wrk->tmp_str));

		/* we already checked for handled */
		if (!li_vrequest_handle_direct(vr))
			return LI_HANDLER_ERROR;

		vr->response.http_status = 401;
		return LI_HANDLER_GO_ON;
	} else {
		/* lets hope browser just ignore the header if status is not 401
		 * but this way it is easier to use a later "auth.deny;"
		 */
		li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("WWW-Authenticate"), GSTR_LEN(vr->wrk->tmp_str));
	}

	if (debug) {
		VR_DEBUG(vr, "client authorization successful for realm \"%s\"", bdata->realm->str);
	}

	return LI_HANDLER_GO_ON;
}
示例#5
0
static int _lua_chunkqueue_add_file(lua_State *L, gboolean tempfile) {
	liChunkQueue *cq;
	const char *filename;
	GString g_filename;
	size_t len;
	struct stat st;
	int fd, err;
	goffset start, length;

	luaL_checkany(L, 2);
	cq = li_lua_get_chunkqueue(L, 1);
	if (cq == NULL) return 0;
	if (!lua_isstring(L, 2)) {
		lua_pushliteral(L, "chunkqueue:add expects filename as first parameter");
		lua_error(L);

		return -1;
	}

	filename = lua_tolstring(L, 2, &len);
	g_filename = li_const_gstring(filename, len);
	if (LI_HANDLER_GO_ON != li_stat_cache_get_sync(NULL, &g_filename, &st, &err, &fd)) {
		lua_pushliteral(L, "chunkqueue:add couldn't open file: ");
		lua_pushvalue(L, 2);
		lua_concat(L, 2);
		lua_error(L);

		return -1;
	}

	start = 0;
	length = st.st_size;

	if (lua_gettop(L) >= 3) {
		if (!lua_isnumber(L, 3)) {
			lua_pushliteral(L, "chunkqueue:add expects number (or nothing) as second parameter");
			lua_error(L);

			close(fd);
			return -1;
		}

		start = lua_tonumber(L, 3);
	}
	if (lua_gettop(L) >= 4) {
		if (!lua_isnumber(L, 4)) {
			lua_pushliteral(L, "chunkqueue:add expects number (or nothing) as third parameter");
			lua_error(L);

			close(fd);
			return -1;
		}

		length = lua_tonumber(L, 3);
	}

	if (start < 0 || start >= st.st_size || length < 0 || start + length > st.st_size) {
		lua_pushliteral(L, "chunkqueue:add: Invalid start/length values");
		lua_error(L);

		close(fd);
		return -1;
	}

	if (tempfile) {
		li_chunkqueue_append_tempfile_fd(cq, g_string_new_len(filename, len), start, length, fd);
	} else {
		li_chunkqueue_append_file_fd(cq, NULL, start, length, fd);
	}

	return 0;
}
示例#6
0
gboolean li_angel_data_write_cstr (GString *buf, const gchar *str, gsize len, GError **err) {
	const GString tmps = li_const_gstring(str, len); /* fake const GString */
	return li_angel_data_write_str(buf, &tmps, err);
}