fix: harden UCE runtime and starter
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
#include "demo_guard.h"
|
||||
|
||||
RENDER(Request& context)
|
||||
{
|
||||
DTree p;
|
||||
p.set(context.params);
|
||||
|
||||
StringList routes = {"index", "dashboard", "themes", "dashboard", "workspace/projects"};
|
||||
StringList unique_routes = list_unique(routes);
|
||||
StringList sorted_routes = list_sort(unique_routes);
|
||||
StringList labels = map(sorted_routes, [](String route) { return(to_upper(replace(route, "/", " / "))); });
|
||||
|
||||
DTree cards;
|
||||
DTree card;
|
||||
card["title"] = "Dashboard"; card["section"] = "app"; card["href"] = "?dashboard"; cards.push(card); card.clear();
|
||||
card["title"] = "Themes"; card["section"] = "app"; card["href"] = "?themes"; cards.push(card); card.clear();
|
||||
card["title"] = "Docs"; card["section"] = "reference"; card["href"] = "../doc/index.uce"; cards.push(card);
|
||||
|
||||
DTree app_cards = dtree_filter(cards, [](DTree item, String key) { return(item["section"].to_string() == "app"); });
|
||||
DTree titles = dtree_map(app_cards, [](DTree item, String key) { DTree out; out = item["title"].to_string(); return(out); });
|
||||
DTree grouped = dtree_group_by(cards, [](DTree item, String key) { return(item["section"].to_string()); });
|
||||
|
||||
<><html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
|
||||
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="index.uce">UCE Test Suite</a><a class="docs-link" href="../doc/index.uce?p=map">Collection Docs →</a></h1>
|
||||
<h2>Collection Helpers</h2>
|
||||
<p>Small data-shaping helpers are useful for route lists, nav records, cards, and other render-adjacent structures.</p>
|
||||
<div class="system-info"><h3>StringList route labels</h3><pre><?= join(labels, "\n") ?></pre></div>
|
||||
<div class="system-info"><h3>DTree app card titles</h3><pre><?= json_encode(titles) ?></pre></div>
|
||||
<div class="system-info"><h3>Grouped cards</h3><pre><?= json_encode(grouped) ?></pre></div>
|
||||
<details>
|
||||
<summary>Request Parameters</summary>
|
||||
<pre><?= var_dump(p) ?></pre>
|
||||
</details>
|
||||
</body>
|
||||
</html></>
|
||||
}
|
||||
@@ -42,6 +42,7 @@ RENDER(Request& context)
|
||||
<? render_card("preprocessor-comments.uce", "Preprocessor Comments", "Regression coverage for comment parsing in templates"); ?>
|
||||
<? render_card("regex.uce", "Regular Expressions", "PCRE2 matching, captures, replacement, and splitting"); ?>
|
||||
<? render_card("string.uce", "String", "String operations"); ?>
|
||||
<? render_card("collections.uce", "Collection Helpers", "Map, filter, group, pick, and omit render data"); ?>
|
||||
<? render_card("str_replace.uce", "String Replace", "Search and replace in strings"); ?>
|
||||
<? render_card("utf8.uce", "UTF-8", "Unicode string handling"); ?>
|
||||
<? render_card("random.uce", "RNG / Noise", "Random generation and noise"); ?>
|
||||
@@ -60,6 +61,7 @@ RENDER(Request& context)
|
||||
<? if(allow_server_demos) { render_card("file_append.uce", "File Append", "Append data to files"); } ?>
|
||||
<? if(allow_server_demos) { render_card("shell.uce", "Shell", "Execute shell commands"); } ?>
|
||||
<? if(allow_server_demos) { render_card("memcached.uce", "Memcached", "Memcached key-value store"); } ?>
|
||||
<? if(allow_server_demos) { render_card("sqlite.uce", "SQLite", "Embedded SQLite database connector"); } ?>
|
||||
<? if(allow_server_demos) { render_card("mysql.uce", "MySQL", "MySQL database connector"); } ?>
|
||||
|
||||
<div class="grid-heading">Advanced</div>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "demo_guard.h"
|
||||
|
||||
RENDER(Request& context)
|
||||
{
|
||||
if(!test_demo_request_allowed(context))
|
||||
{
|
||||
test_demo_render_restricted_html(context, "SQLite demo", "write to a server-side SQLite database");
|
||||
return;
|
||||
}
|
||||
|
||||
String db_path = "/tmp/uce-demo-sqlite.sqlite";
|
||||
SQLite* db = sqlite_connect(db_path);
|
||||
sqlite_query(db, "create table if not exists notes(id integer primary key autoincrement, body text not null, created_at text not null)");
|
||||
|
||||
if(context.params["REQUEST_METHOD"] == "POST" && trim(context.post["body"]) != "")
|
||||
{
|
||||
StringMap params;
|
||||
params["body"] = trim(context.post["body"]);
|
||||
params["created_at"] = time_format_utc("%Y-%m-%d %H:%M:%S");
|
||||
sqlite_query(db, "insert into notes(body, created_at) values(:body, :created_at)", params);
|
||||
sqlite_disconnect(db);
|
||||
redirect("sqlite.uce", 303);
|
||||
return;
|
||||
}
|
||||
|
||||
DTree notes = sqlite_query(db, "select id, body, created_at from notes order by id desc limit 10");
|
||||
String error = sqlite_error(db);
|
||||
?><html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
|
||||
<link rel="stylesheet" href="style.css?v=<?= time() ?>"></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1><a href="index.uce">UCE Demo</a> / SQLite</h1>
|
||||
<div class="system-info">
|
||||
<p>This demo stores rows in <code><?= db_path ?></code> with runtime SQLite helpers and named prepared parameters.</p>
|
||||
<form method="post">
|
||||
<input name="body" placeholder="note text"></input>
|
||||
<button type="submit">Add note</button>
|
||||
</form>
|
||||
<? if(error != "ok" && error != "connected") { ?><pre><?= error ?></pre><? } ?>
|
||||
</div>
|
||||
<div class="test-grid">
|
||||
<? notes.each([&](DTree note, String key) { ?>
|
||||
<div class="test-card">
|
||||
<strong>#<?= note["id"].to_string() ?> <?= note["created_at"].to_string() ?></strong>
|
||||
<span><?= note["body"].to_string() ?></span>
|
||||
</div>
|
||||
<? }); ?>
|
||||
</div>
|
||||
</body>
|
||||
</html><?
|
||||
sqlite_disconnect(db);
|
||||
}
|
||||
Reference in New Issue
Block a user