/* 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; }
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); }
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; }
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; }
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; }
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); }