This commit is contained in:
2025-09-26 11:34:48 +02:00
parent c9038b8fac
commit e50dfd518b
4 changed files with 219 additions and 121 deletions
+1 -1
View File
@@ -87,4 +87,4 @@ void wl_push_array (WL_Runtime *rt, int cap);
void wl_push_map (WL_Runtime *rt, int cap); void wl_push_map (WL_Runtime *rt, int cap);
void wl_push_arg (WL_Runtime *rt, int idx); void wl_push_arg (WL_Runtime *rt, int idx);
void wl_insert (WL_Runtime *rt); void wl_insert (WL_Runtime *rt);
void wl_append (WL_Runtime *rt); void wl_append (WL_Runtime *rt);
+125 -76
View File
@@ -1,8 +1,8 @@
/* /*
Copyright © 2025 Francesco Cozzuto Copyright 2025 Francesco Cozzuto
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the Software), copy of this software and associated documentation files (the Software),
to deal in the Software without restriction, including without limitation to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the and/or sell copies of the Software, and to permit persons to whom the
@@ -11,7 +11,7 @@ Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software. in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
@@ -26,14 +26,14 @@ OTHER DEALINGS IN THE SOFTWARE.
// src/main.h // src/main.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/main.h" //#line 1 "src/main.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#define CWEB_ENABLE_DATABASE #define CWEB_ENABLE_DATABASE
#define CWEB_ENABLE_TEMPLATE #define CWEB_ENABLE_TEMPLATE
#define CWEB_STR(X) (CWEB_String) { (X), (int) sizeof(X)-1 } #define CWEB_STR(X) ((CWEB_String) { (X), (int) sizeof(X)-1 })
typedef struct { typedef struct {
char *ptr; char *ptr;
@@ -258,6 +258,9 @@ int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String sche
// Log all evaluated SQL statements to stdout // Log all evaluated SQL statements to stdout
void cweb_trace_sql(CWEB *cweb, bool enable); void cweb_trace_sql(CWEB *cweb, bool enable);
// TODO: comment
void cweb_enable_template_cache(CWEB *cweb, bool enable);
// Pause execution until a request is available. // Pause execution until a request is available.
// TODO: When does this function return NULL? // TODO: When does this function return NULL?
CWEB_Request *cweb_wait(CWEB *cweb); CWEB_Request *cweb_wait(CWEB *cweb);
@@ -275,6 +278,9 @@ int cweb_get_user_id(CWEB_Request *req);
// If the ID is -1, the session is deleted. // If the ID is -1, the session is deleted.
int cweb_set_user_id(CWEB_Request *req, int user_id); int cweb_set_user_id(CWEB_Request *req, int user_id);
// TODO: comment
CWEB_String cweb_get_path(CWEB_Request *req);
// Returns the request parameter with the specified name // Returns the request parameter with the specified name
// If the request uses POST, the parameter is taken from the body, // If the request uses POST, the parameter is taken from the body,
// else it's taken from the URL. If the parameter is not present, // else it's taken from the URL. If the parameter is not present,
@@ -299,13 +305,18 @@ void cweb_respond_basic(CWEB_Request *req, int status, CWEB_String content);
void cweb_respond_redirect(CWEB_Request *req, CWEB_String target); void cweb_respond_redirect(CWEB_Request *req, CWEB_String target);
// Responds to the request by evaluating a WL template file // Responds to the request by evaluating a WL template file
void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_file, int resource_id); void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args);
// Helper
#define cweb_respond_template(req, status, template_file, ...) \
cweb_respond_template_impl((req), (status), (template_file), CWEB_VARGS(__VA_ARGS__))
// Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned // Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned
int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args); int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
// Helper // Helper
#define cweb_database_insert(cweb, fmt, ...) cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__)) #define cweb_database_insert(cweb, fmt, ...) \
cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
// Iterator over database rows // Iterator over database rows
typedef struct { void *handle; } CWEB_QueryResult; typedef struct { void *handle; } CWEB_QueryResult;
@@ -347,7 +358,7 @@ int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
// 3p/chttp.h // 3p/chttp.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/chttp.h" //#line 1 "3p/chttp.h"
#ifndef HTTP_AMALGAMATION #ifndef HTTP_AMALGAMATION
#define HTTP_AMALGAMATION #define HTTP_AMALGAMATION
@@ -357,7 +368,7 @@ int cweb_check_password(CWEB_String pass, CWEB_PasswordHash hash);
// src/basic.h // src/basic.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/basic.h" //#line 1 "src/basic.h"
#ifndef CHTTP_BASIC_INCLUDED #ifndef CHTTP_BASIC_INCLUDED
#define CHTTP_BASIC_INCLUDED #define CHTTP_BASIC_INCLUDED
@@ -444,7 +455,7 @@ void print_bytes(HTTP_String prefix, HTTP_String src);
// src/parse.h // src/parse.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/parse.h" //#line 1 "src/parse.h"
#ifndef PARSE_INCLUDED #ifndef PARSE_INCLUDED
#define PARSE_INCLUDED #define PARSE_INCLUDED
@@ -550,7 +561,7 @@ int http_get_param_i (HTTP_String body, HTTP_String str);
// src/engine.h // src/engine.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/engine.h" //#line 1 "src/engine.h"
#ifndef HTTP_ENGINE_INCLUDED #ifndef HTTP_ENGINE_INCLUDED
#define HTTP_ENGINE_INCLUDED #define HTTP_ENGINE_INCLUDED
@@ -678,7 +689,7 @@ void http_engine_undo (HTTP_Engine *eng);
// src/cert.h // src/cert.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/cert.h" //#line 1 "src/cert.h"
#ifndef CERT_INCLUDED #ifndef CERT_INCLUDED
#define CERT_INCLUDED #define CERT_INCLUDED
@@ -709,7 +720,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
// src/client.h // src/client.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/client.h" //#line 1 "src/client.h"
#ifndef CLIENT_INCLUDED #ifndef CLIENT_INCLUDED
#define CLIENT_INCLUDED #define CLIENT_INCLUDED
@@ -813,7 +824,7 @@ HTTP_Response *http_post(HTTP_String url,
// src/server.h // src/server.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/server.h" //#line 1 "src/server.h"
#ifndef HTTP_SERVER_INCLUDED #ifndef HTTP_SERVER_INCLUDED
#define HTTP_SERVER_INCLUDED #define HTTP_SERVER_INCLUDED
@@ -854,7 +865,7 @@ void http_response_builder_done (HTTP_ResponseBuilder res);
// src/router.h // src/router.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/router.h" //#line 1 "src/router.h"
#ifndef HTTP_ROUTER_INCLUDED #ifndef HTTP_ROUTER_INCLUDED
#define HTTP_ROUTER_INCLUDED #define HTTP_ROUTER_INCLUDED
@@ -879,7 +890,7 @@ int http_serve (char *addr, int port, HTTP_Router *router);
// 3p/chttp.c // 3p/chttp.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/chttp.c" //#line 1 "3p/chttp.c"
#ifndef HTTP_NOINCLUDE #ifndef HTTP_NOINCLUDE
#include "chttp.h" #include "chttp.h"
#endif #endif
@@ -888,7 +899,7 @@ int http_serve (char *addr, int port, HTTP_Router *router);
// src/sec.h // src/sec.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/sec.h" //#line 1 "src/sec.h"
#ifndef SEC_INCLUDED #ifndef SEC_INCLUDED
#define SEC_INCLUDED #define SEC_INCLUDED
@@ -949,7 +960,7 @@ void secure_context_free(SecureContext *sec);
// src/socket_raw.h // src/socket_raw.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket_raw.h" //#line 1 "src/socket_raw.h"
#ifndef SOCKET_RAW_INCLUDED #ifndef SOCKET_RAW_INCLUDED
#define SOCKET_RAW_INCLUDED #define SOCKET_RAW_INCLUDED
@@ -990,7 +1001,7 @@ RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
// src/socket.h // src/socket.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket.h" //#line 1 "src/socket.h"
#ifndef SOCKET_INCLUDED #ifndef SOCKET_INCLUDED
#define SOCKET_INCLUDED #define SOCKET_INCLUDED
@@ -1071,7 +1082,7 @@ void* socket_get_user_data(Socket *sock);
// src/socket_pool.h // src/socket_pool.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket_pool.h" //#line 1 "src/socket_pool.h"
#ifndef SOCKET_POOL_INCLUDED #ifndef SOCKET_POOL_INCLUDED
#define SOCKET_POOL_INCLUDED #define SOCKET_POOL_INCLUDED
@@ -1137,7 +1148,7 @@ bool socket_pool_secure(SocketPool *pool, SocketHandle handle);
// src/basic.c // src/basic.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/basic.c" //#line 1 "src/basic.c"
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
@@ -1246,7 +1257,7 @@ void print_bytes(HTTP_String prefix, HTTP_String src)
// src/parse.c // src/parse.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/parse.c" //#line 1 "src/parse.c"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -2553,7 +2564,7 @@ int http_get_param_i(HTTP_String body, HTTP_String str)
// src/engine.c // src/engine.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/engine.c" //#line 1 "src/engine.c"
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@@ -3547,7 +3558,7 @@ void http_engine_undo(HTTP_Engine *eng)
// src/cert.c // src/cert.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/cert.c" //#line 1 "src/cert.c"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -3722,7 +3733,7 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
// src/sec.c // src/sec.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/sec.c" //#line 1 "src/sec.c"
#ifndef HTTP_AMALGAMATION #ifndef HTTP_AMALGAMATION
#include "sec.h" #include "sec.h"
#endif #endif
@@ -3948,7 +3959,7 @@ int secure_context_add_cert(SecureContext *sec,
// src/socket_raw.c // src/socket_raw.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket_raw.c" //#line 1 "src/socket_raw.c"
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
@@ -4060,7 +4071,7 @@ RAW_SOCKET listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
// src/socket.c // src/socket.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket.c" //#line 1 "src/socket.c"
#include <stdio.h> // snprintf #include <stdio.h> // snprintf
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@@ -4856,7 +4867,7 @@ void *socket_get_user_data(Socket *sock)
// src/socket_pool.c // src/socket_pool.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/socket_pool.c" //#line 1 "src/socket_pool.c"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
@@ -5219,7 +5230,7 @@ bool socket_pool_secure(SocketPool *pool, SocketHandle handle)
// src/client.c // src/client.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/client.c" //#line 1 "src/client.c"
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
@@ -5678,7 +5689,7 @@ HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers,
// src/server.c // src/server.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/server.c" //#line 1 "src/server.c"
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -5991,7 +6002,7 @@ void http_response_builder_done(HTTP_ResponseBuilder res)
// src/router.c // src/router.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/router.c" //#line 1 "src/router.c"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
@@ -6458,7 +6469,7 @@ int http_serve(char *addr, int port, HTTP_Router *router)
// 3p/wl.h // 3p/wl.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/wl.h" //#line 1 "3p/wl.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@@ -6554,7 +6565,7 @@ void wl_append (WL_Runtime *rt);
// 3p/wl.c // 3p/wl.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/wl.c" //#line 1 "3p/wl.c"
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -12437,7 +12448,7 @@ void wl_runtime_dump(WL_Runtime *rt)
// 3p/crypt_blowfish.h // 3p/crypt_blowfish.h
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/crypt_blowfish.h" //#line 1 "3p/crypt_blowfish.h"
/* /*
* Written by Solar Designer <solar at openwall.com> in 2000-2011. * Written by Solar Designer <solar at openwall.com> in 2000-2011.
* No copyright is claimed, and the software is hereby placed in the public * No copyright is claimed, and the software is hereby placed in the public
@@ -12470,7 +12481,7 @@ extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
// 3p/crypt_blowfish.c // 3p/crypt_blowfish.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "3p/crypt_blowfish.c" //#line 1 "3p/crypt_blowfish.c"
/* /*
* The crypt_blowfish homepage is: * The crypt_blowfish homepage is:
* *
@@ -13385,7 +13396,7 @@ char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
// src/main.c // src/main.c
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#line 1 "src/main.c" //#line 1 "src/main.c"
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
@@ -13489,6 +13500,7 @@ struct CWEB {
#ifdef CWEB_ENABLE_TEMPLATE #ifdef CWEB_ENABLE_TEMPLATE
TemplateCache *tpcache; TemplateCache *tpcache;
bool enable_template_cache;
#endif #endif
bool allow_insecure_login; bool allow_insecure_login;
@@ -14334,6 +14346,7 @@ CWEB *cweb_init(CWEB_String addr, uint16_t port)
free(cweb); free(cweb);
return NULL; return NULL;
} }
cweb->enable_template_cache = true;
#endif #endif
cweb->session_storage = session_storage_init(1024); cweb->session_storage = session_storage_init(1024);
@@ -14401,6 +14414,11 @@ void cweb_trace_sql(CWEB *cweb, bool enable)
#endif #endif
} }
void cweb_enable_template_cache(CWEB *cweb, bool enable)
{
cweb->enable_template_cache = enable;
}
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file) int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file)
{ {
#ifdef CWEB_ENABLE_DATABASE #ifdef CWEB_ENABLE_DATABASE
@@ -14478,6 +14496,12 @@ bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str)
return http_streq(req->req->url.path, (HTTP_String) { str.ptr, str.len }); return http_streq(req->req->url.path, (HTTP_String) { str.ptr, str.len });
} }
CWEB_String cweb_get_path(CWEB_Request *req)
{
HTTP_String path = req->req->url.path;
return (CWEB_String) { path.ptr, path.len };
}
CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name) CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name)
{ {
HTTP_String src = req->req->url.query; HTTP_String src = req->req->url.query;
@@ -14843,47 +14867,18 @@ static int query_routine(WL_Runtime *rt, SQLiteCache *dbcache)
return 0; return 0;
} }
static void push_sysvar(WL_Runtime *rt, WL_String name, SQLiteCache *dbcache, CWEB_String csrf, int user_id, int resource_id) static int get_or_create_program(TemplateCache *cache, WL_String path, bool force_create, WL_Arena *arena, WL_Program *program)
{
(void) dbcache;
if (wl_streq(name, "login_user_id", -1)) {
if (user_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, user_id);
} else if (wl_streq(name, "resource_id", -1)) {
if (resource_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, resource_id);
} else if (wl_streq(name, "csrf", -1)) {
if (csrf.len == 0)
wl_push_none(rt);
else
wl_push_str(rt, (WL_String) { csrf.ptr, csrf.len });
}
}
static void push_syscall(WL_Runtime *rt, WL_String name, SQLiteCache *dbcache)
{
if (wl_streq(name, "query", -1)) {
query_routine(rt, dbcache);
return;
}
}
static int get_or_create_program(TemplateCache *cache, WL_String path, WL_Arena *arena, WL_Program *program)
{ {
if (cache == NULL) if (cache == NULL)
return -1; return -1;
int i = template_cache_lookup(cache, path); int i = template_cache_lookup(cache, path);
if (cache->pool[i].pathlen != -1 && force_create) {
cache->pool[i].pathlen = -1;
free(cache->pool[i].program.ptr);
}
if (cache->pool[i].pathlen == -1) { if (cache->pool[i].pathlen == -1) {
WL_Program program; WL_Program program;
@@ -14909,7 +14904,7 @@ static int get_or_create_program(TemplateCache *cache, WL_String path, WL_Arena
} }
#endif #endif
void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_file, int resource_id) void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args)
{ {
#ifdef CWEB_ENABLE_TEMPLATE #ifdef CWEB_ENABLE_TEMPLATE
http_response_builder_status(req->builder, status); http_response_builder_status(req->builder, status);
@@ -14922,7 +14917,7 @@ void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_f
} }
WL_Program program; WL_Program program;
ret = get_or_create_program(req->cweb->tpcache, (WL_String) { template_file.ptr, template_file.len }, &req->arena, &program); ret = get_or_create_program(req->cweb->tpcache, (WL_String) { template_file.ptr, template_file.len }, !req->cweb->enable_template_cache, &req->arena, &program);
if (ret < 0) { if (ret < 0) {
http_response_builder_undo(req->builder); http_response_builder_undo(req->builder);
http_response_builder_status(req->builder, 500); http_response_builder_status(req->builder, 500);
@@ -14958,11 +14953,65 @@ void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_f
return; return;
case WL_EVAL_SYSVAR: case WL_EVAL_SYSVAR:
push_sysvar(rt, result.str, req->cweb->dbcache, req->csrf, req->user_id, resource_id); if (wl_streq(result.str, "login_user_id", -1)) {
if (req->user_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, req->user_id);
} else if (wl_streq(result.str, "csrf", -1)) {
if (req->csrf.len == 0)
wl_push_none(rt);
else
wl_push_str(rt, (WL_String) { req->csrf.ptr, req->csrf.len });
}
break; break;
case WL_EVAL_SYSCALL: case WL_EVAL_SYSCALL:
push_syscall(rt, result.str, req->cweb->dbcache); if (wl_streq(result.str, "query", -1)) {
query_routine(rt, req->cweb->dbcache);
break;
}
if (wl_streq(result.str, "args", -1)) {
if (wl_arg_count(rt) != 1) {
// TODO
break;
}
int64_t idx;
if (!wl_arg_s64(rt, 0, &idx)) {
// TODO
break;
}
if (idx < 0 || idx >= args.len) {
// TODO
break;
}
CWEB_VArg arg = args.ptr[idx];
switch (arg.type) {
case CWEB_VARG_TYPE_C : wl_push_s64(rt, arg.c); break;
case CWEB_VARG_TYPE_S : wl_push_s64(rt, arg.s); break;
case CWEB_VARG_TYPE_I : wl_push_s64(rt, arg.i); break;
case CWEB_VARG_TYPE_L : wl_push_s64(rt, arg.l); break;
case CWEB_VARG_TYPE_LL : wl_push_s64(rt, arg.ll); break;
case CWEB_VARG_TYPE_SC : wl_push_s64(rt, arg.sc); break;
case CWEB_VARG_TYPE_SS : wl_push_s64(rt, arg.ss); break;
case CWEB_VARG_TYPE_SI : wl_push_s64(rt, arg.si); break;
case CWEB_VARG_TYPE_SL : wl_push_s64(rt, arg.sl); break;
case CWEB_VARG_TYPE_SLL: wl_push_s64(rt, arg.sll); break;
case CWEB_VARG_TYPE_F : wl_push_f64(rt, arg.f); break;
case CWEB_VARG_TYPE_D : wl_push_s64(rt, arg.d); break;
case CWEB_VARG_TYPE_B : if (arg.b) wl_push_true(rt); else wl_push_false(rt); break;
case CWEB_VARG_TYPE_STR: wl_push_str(rt, (WL_String) { arg.str.ptr, arg.str.len }); break;
default:break;
}
break;
}
break; break;
case WL_EVAL_OUTPUT: case WL_EVAL_OUTPUT:
+79 -41
View File
@@ -101,6 +101,7 @@ struct CWEB {
#ifdef CWEB_ENABLE_TEMPLATE #ifdef CWEB_ENABLE_TEMPLATE
TemplateCache *tpcache; TemplateCache *tpcache;
bool enable_template_cache;
#endif #endif
bool allow_insecure_login; bool allow_insecure_login;
@@ -672,7 +673,7 @@ static int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, char *
if (cache->items[i].stmt == NULL) { if (cache->items[i].stmt == NULL) {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int ret = sqlite3_prepare_v2(cache->db, fmt, -1, &stmt, NULL); int ret = sqlite3_prepare_v2(cache->db, fmt, fmtlen, &stmt, NULL);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
fprintf(stderr, "Failed to prepare statement: %s (%s:%d)\n", sqlite3_errmsg(cache->db), __FILE__, __LINE__); // TODO fprintf(stderr, "Failed to prepare statement: %s (%s:%d)\n", sqlite3_errmsg(cache->db), __FILE__, __LINE__); // TODO
return ret; return ret;
@@ -946,6 +947,7 @@ CWEB *cweb_init(CWEB_String addr, uint16_t port)
free(cweb); free(cweb);
return NULL; return NULL;
} }
cweb->enable_template_cache = true;
#endif #endif
cweb->session_storage = session_storage_init(1024); cweb->session_storage = session_storage_init(1024);
@@ -1013,6 +1015,11 @@ void cweb_trace_sql(CWEB *cweb, bool enable)
#endif #endif
} }
void cweb_enable_template_cache(CWEB *cweb, bool enable)
{
cweb->enable_template_cache = enable;
}
int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file) int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String schema_file)
{ {
#ifdef CWEB_ENABLE_DATABASE #ifdef CWEB_ENABLE_DATABASE
@@ -1090,6 +1097,12 @@ bool cweb_match_endpoint(CWEB_Request *req, CWEB_String str)
return http_streq(req->req->url.path, (HTTP_String) { str.ptr, str.len }); return http_streq(req->req->url.path, (HTTP_String) { str.ptr, str.len });
} }
CWEB_String cweb_get_path(CWEB_Request *req)
{
HTTP_String path = req->req->url.path;
return (CWEB_String) { path.ptr, path.len };
}
CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name) CWEB_String cweb_get_param_s(CWEB_Request *req, CWEB_String name)
{ {
HTTP_String src = req->req->url.query; HTTP_String src = req->req->url.query;
@@ -1455,47 +1468,18 @@ static int query_routine(WL_Runtime *rt, SQLiteCache *dbcache)
return 0; return 0;
} }
static void push_sysvar(WL_Runtime *rt, WL_String name, SQLiteCache *dbcache, CWEB_String csrf, int user_id, int resource_id) static int get_or_create_program(TemplateCache *cache, WL_String path, bool force_create, WL_Arena *arena, WL_Program *program)
{
(void) dbcache;
if (wl_streq(name, "login_user_id", -1)) {
if (user_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, user_id);
} else if (wl_streq(name, "resource_id", -1)) {
if (resource_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, resource_id);
} else if (wl_streq(name, "csrf", -1)) {
if (csrf.len == 0)
wl_push_none(rt);
else
wl_push_str(rt, (WL_String) { csrf.ptr, csrf.len });
}
}
static void push_syscall(WL_Runtime *rt, WL_String name, SQLiteCache *dbcache)
{
if (wl_streq(name, "query", -1)) {
query_routine(rt, dbcache);
return;
}
}
static int get_or_create_program(TemplateCache *cache, WL_String path, WL_Arena *arena, WL_Program *program)
{ {
if (cache == NULL) if (cache == NULL)
return -1; return -1;
int i = template_cache_lookup(cache, path); int i = template_cache_lookup(cache, path);
if (cache->pool[i].pathlen != -1 && force_create) {
cache->pool[i].pathlen = -1;
free(cache->pool[i].program.ptr);
}
if (cache->pool[i].pathlen == -1) { if (cache->pool[i].pathlen == -1) {
WL_Program program; WL_Program program;
@@ -1521,7 +1505,7 @@ static int get_or_create_program(TemplateCache *cache, WL_String path, WL_Arena
} }
#endif #endif
void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_file, int resource_id) void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args)
{ {
#ifdef CWEB_ENABLE_TEMPLATE #ifdef CWEB_ENABLE_TEMPLATE
http_response_builder_status(req->builder, status); http_response_builder_status(req->builder, status);
@@ -1534,7 +1518,7 @@ void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_f
} }
WL_Program program; WL_Program program;
ret = get_or_create_program(req->cweb->tpcache, (WL_String) { template_file.ptr, template_file.len }, &req->arena, &program); ret = get_or_create_program(req->cweb->tpcache, (WL_String) { template_file.ptr, template_file.len }, !req->cweb->enable_template_cache, &req->arena, &program);
if (ret < 0) { if (ret < 0) {
http_response_builder_undo(req->builder); http_response_builder_undo(req->builder);
http_response_builder_status(req->builder, 500); http_response_builder_status(req->builder, 500);
@@ -1570,11 +1554,65 @@ void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_f
return; return;
case WL_EVAL_SYSVAR: case WL_EVAL_SYSVAR:
push_sysvar(rt, result.str, req->cweb->dbcache, req->csrf, req->user_id, resource_id); if (wl_streq(result.str, "login_user_id", -1)) {
if (req->user_id < 0)
wl_push_none(rt);
else
wl_push_s64(rt, req->user_id);
} else if (wl_streq(result.str, "csrf", -1)) {
if (req->csrf.len == 0)
wl_push_none(rt);
else
wl_push_str(rt, (WL_String) { req->csrf.ptr, req->csrf.len });
}
break; break;
case WL_EVAL_SYSCALL: case WL_EVAL_SYSCALL:
push_syscall(rt, result.str, req->cweb->dbcache); if (wl_streq(result.str, "query", -1)) {
query_routine(rt, req->cweb->dbcache);
break;
}
if (wl_streq(result.str, "args", -1)) {
if (wl_arg_count(rt) != 1) {
// TODO
break;
}
int64_t idx;
if (!wl_arg_s64(rt, 0, &idx)) {
// TODO
break;
}
if (idx < 0 || idx >= args.len) {
// TODO
break;
}
CWEB_VArg arg = args.ptr[idx];
switch (arg.type) {
case CWEB_VARG_TYPE_C : wl_push_s64(rt, arg.c); break;
case CWEB_VARG_TYPE_S : wl_push_s64(rt, arg.s); break;
case CWEB_VARG_TYPE_I : wl_push_s64(rt, arg.i); break;
case CWEB_VARG_TYPE_L : wl_push_s64(rt, arg.l); break;
case CWEB_VARG_TYPE_LL : wl_push_s64(rt, arg.ll); break;
case CWEB_VARG_TYPE_SC : wl_push_s64(rt, arg.sc); break;
case CWEB_VARG_TYPE_SS : wl_push_s64(rt, arg.ss); break;
case CWEB_VARG_TYPE_SI : wl_push_s64(rt, arg.si); break;
case CWEB_VARG_TYPE_SL : wl_push_s64(rt, arg.sl); break;
case CWEB_VARG_TYPE_SLL: wl_push_s64(rt, arg.sll); break;
case CWEB_VARG_TYPE_F : wl_push_f64(rt, arg.f); break;
case CWEB_VARG_TYPE_D : wl_push_s64(rt, arg.d); break;
case CWEB_VARG_TYPE_B : if (arg.b) wl_push_true(rt); else wl_push_false(rt); break;
case CWEB_VARG_TYPE_STR: wl_push_str(rt, (WL_String) { arg.str.ptr, arg.str.len }); break;
default:break;
}
break;
}
break; break;
case WL_EVAL_OUTPUT: case WL_EVAL_OUTPUT:
+14 -3
View File
@@ -4,7 +4,7 @@
#define CWEB_ENABLE_DATABASE #define CWEB_ENABLE_DATABASE
#define CWEB_ENABLE_TEMPLATE #define CWEB_ENABLE_TEMPLATE
#define CWEB_STR(X) (CWEB_String) { (X), (int) sizeof(X)-1 } #define CWEB_STR(X) ((CWEB_String) { (X), (int) sizeof(X)-1 })
typedef struct { typedef struct {
char *ptr; char *ptr;
@@ -229,6 +229,9 @@ int cweb_enable_database(CWEB *cweb, CWEB_String database_file, CWEB_String sche
// Log all evaluated SQL statements to stdout // Log all evaluated SQL statements to stdout
void cweb_trace_sql(CWEB *cweb, bool enable); void cweb_trace_sql(CWEB *cweb, bool enable);
// TODO: comment
void cweb_enable_template_cache(CWEB *cweb, bool enable);
// Pause execution until a request is available. // Pause execution until a request is available.
// TODO: When does this function return NULL? // TODO: When does this function return NULL?
CWEB_Request *cweb_wait(CWEB *cweb); CWEB_Request *cweb_wait(CWEB *cweb);
@@ -246,6 +249,9 @@ int cweb_get_user_id(CWEB_Request *req);
// If the ID is -1, the session is deleted. // If the ID is -1, the session is deleted.
int cweb_set_user_id(CWEB_Request *req, int user_id); int cweb_set_user_id(CWEB_Request *req, int user_id);
// TODO: comment
CWEB_String cweb_get_path(CWEB_Request *req);
// Returns the request parameter with the specified name // Returns the request parameter with the specified name
// If the request uses POST, the parameter is taken from the body, // If the request uses POST, the parameter is taken from the body,
// else it's taken from the URL. If the parameter is not present, // else it's taken from the URL. If the parameter is not present,
@@ -270,13 +276,18 @@ void cweb_respond_basic(CWEB_Request *req, int status, CWEB_String content);
void cweb_respond_redirect(CWEB_Request *req, CWEB_String target); void cweb_respond_redirect(CWEB_Request *req, CWEB_String target);
// Responds to the request by evaluating a WL template file // Responds to the request by evaluating a WL template file
void cweb_respond_template(CWEB_Request *req, int status, CWEB_String template_file, int resource_id); void cweb_respond_template_impl(CWEB_Request *req, int status, CWEB_String template_file, CWEB_VArgs args);
// Helper
#define cweb_respond_template(req, status, template_file, ...) \
cweb_respond_template_impl((req), (status), (template_file), CWEB_VARGS(__VA_ARGS__))
// Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned // Evaluates an SQL INSERT statement and returns the ID of the last inserted row. On error -1 is returned
int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args); int64_t cweb_database_insert_impl(CWEB *cweb, char *fmt, CWEB_VArgs args);
// Helper // Helper
#define cweb_database_insert(cweb, fmt, ...) cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__)) #define cweb_database_insert(cweb, fmt, ...) \
cweb_database_insert_impl((cweb), (fmt), CWEB_VARGS(__VA_ARGS__))
// Iterator over database rows // Iterator over database rows
typedef struct { void *handle; } CWEB_QueryResult; typedef struct { void *handle; } CWEB_QueryResult;