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