trying to port web app starter from PHP

This commit is contained in:
udo
2026-04-19 09:38:23 +00:00
parent 46d98a092f
commit be514d63d6
546 changed files with 76910 additions and 2807 deletions
+20
View File
@@ -0,0 +1,20 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
call_file()
</h1>
<pre><?
call_file("call_file_funcs.uce", "test_func");
print("\n");
render_file("call_file_funcs.uce", context);
?></pre>
<pre><?= var_dump(context.params) ?></pre>
</>
}
+6
View File
@@ -0,0 +1,6 @@
// Minimal exported helper used by the `call_file()` demo page.
EXPORT void test_func()
{
print("HELLO FROM TEST FUNCTION");
}
+33
View File
@@ -0,0 +1,33 @@
RENDER(Request& context)
{
DTree card_props;
card_props["title"] = "Component Example";
card_props["body"] = "This card body comes from context.call and is rendered through component().";
DTree named_props;
named_props["title"] = "Named Render Example";
named_props["body"] = "This content is rendered through the RENDER:BODY(Request& context) entry point.";
<>
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Components
</h1>
<p>
component_exists("components/card"):
<strong><?= component_exists("components/card") ? "true" : "false" ?></strong>
</p>
<p>
component_resolve("components/card"):
<code><?= component_resolve("components/card") ?></code>
</p>
<h2>Default Render</h2>
<div>
<?: component("components/card", card_props, context) ?>
</div>
<h2>Named Render</h2>
<? render_component("components/card:BODY", named_props, context); ?>
</>
}
+24
View File
@@ -0,0 +1,24 @@
RENDER(Request& context)
{
<>
<section style="border:1px solid #ccc;padding:1em;margin:1em 0;">
<? render_component("card:TITLE", context.call, context); ?>
<? render_component("card:BODY", context.call, context); ?>
</section>
</>
}
RENDER:TITLE(Request& context)
{
<>
<h3><?= first(context.call["title"].to_string(), "Component Title") ?></h3>
</>
}
RENDER:BODY(Request& context)
{
<>
<p><?= first(context.call["body"].to_string(), "Component Body") ?></p>
</>
}
@@ -0,0 +1,10 @@
RENDER(Request& context)
{
String lang = first(context.call["lang"].to_string(), "plain");
<>
<section>
<p><strong>Code block:</strong> <?= lang ?></p>
<div><?: context.call["default_html"].to_string() ?></div>
</section>
</>
}
+15
View File
@@ -0,0 +1,15 @@
RENDER(Request& context)
{
String title = first(
context.call["node"]["attrs"]["title"].to_string(),
context.call["argument"].to_string(),
"Notice"
);
<>
<aside>
<p><strong><?= title ?></strong></p>
<div><?: context.call["children_html"].to_string() ?></div>
</aside>
</>
}
+30
View File
@@ -0,0 +1,30 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Cookies
</h1>
Set
<pre><?
set_cookie("test-cookie-1", "test-value-1", time() + 30*60);
set_cookie("test-cookie-2", "test-value-2", time() + 30*60*24);
print(var_dump(context.set_cookies));
?></pre>
Get
<pre><?
print(var_dump(context.cookies));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+54
View File
@@ -0,0 +1,54 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
DTree
</h1>
Value Types:
<pre><?
t.set("String test");
print(String("String test: ") + t.to_string()+"\n");
t.set(true);
print(String("bool test: ") + t.to_string()+"\n");
t.set(1234.5678);
print(String("float test: ") + t.to_string()+"\n");
t.set(&t);
print(String("pointer test: ") + t.to_string()+"\n");
?></pre>
Tree:
<pre><?
t.key("a")->set("valueA");
t.key("b")->set("valueB");
t.key("c")->key("c-d")->set("valueCD");
t.key("c")->key("c-e")->set("valueCE");
t.key("c")->key("c-f")->set(&t);
t.key("g")->key("g-h")->key("h-i")->set("valueHI");
t["g"]["x"]["y1"] = "XYZ1";
t["g"]["x"]["y2"] = &t;
t["g"]["x"]["y3"] = time();
t["g"]["x"]["y4"] = "Ünicödä";
print(var_dump(t));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+4
View File
@@ -0,0 +1,4 @@
void hello()
{
}
+26
View File
@@ -0,0 +1,26 @@
RENDER(Request& context)
{
String mode = context.get["mode"];
if(mode == "exception")
throw std::runtime_error("Intentional test exception from /test/error-reporting.uce");
if(mode == "abort")
raise(SIGABRT);
if(mode == "segfault")
raise(SIGSEGV);
<>
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Error reporting
</h1>
<p>These actions intentionally trigger failures so you can verify that UCE returns a usable `500` response instead of dropping the upstream connection.</p>
<ul>
<li><a href="?mode=exception">Trigger uncaught exception</a></li>
<li><a href="?mode=abort">Trigger SIGABRT</a></li>
<li><a href="?mode=segfault">Trigger SIGSEGV</a></li>
</ul>
</>
}
+36
View File
@@ -0,0 +1,36 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
File Append
</h1>
File Append:
<pre style="white-space: pre-wrap"><?
if(context.get["cmd"] == "clear")
file_put_contents("/tmp/test.txt", "");
file_append("/tmp/test.txt", context.server->request_count, "\thello world\t", 2, "\t", time(), "\t", microtime(), "\n");
print(file_get_contents("/tmp/test.txt"));
?></pre>
<button onclick="document.location.href='?cmd=add';">Add Line</button>
<button onclick="document.location.href='?cmd=clear';">Clear File</button>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+22
View File
@@ -0,0 +1,22 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
FileI/O
</h1>
File IO:
<pre style="white-space: pre-wrap"><?= file_get_contents("fileio.uce") ?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+25
View File
@@ -0,0 +1,25 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Header
</h1>
Response Headers
<pre style="white-space: pre-wrap"><?
print(var_dump(context.header));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+189
View File
@@ -0,0 +1,189 @@
void show_stuff(Request& context)
{
//context.header["Content-Type"] = "text/plain";
<><html>
Mwahahaaha <?= time() ?>
<div>hello world: <?= context.params["HTTP_HOST"] ?></div>
<pre>
Display the date using any or all of the following elements:
%a: abbreviated day name (i.e. mon, tue, wed)
%A: full day name (i.e. Monday, Tuesday, Wednesday)
%b or %h: abbreviated month name (i.e. jan, feb, mar)
%B: full month name (January, February, March)
%c: locales date and time (full date and time)
%C: century - displays the first two numbers of the year (i.e 19 for 1999 and 20 for 2020)
%d: day of month (i.e. 01, 02, 03)
%D: same as M/D/Y (i.e. 04/20/16)
%e: day of month padded (i.e. ' 1', ' 2')
%F: full date, same as yyyy-mm-dd
%H: hour (00, 01, 02, 21, 22, 23)
%I: hour (1,2,3,10,11,12)
%j: day of year (i.e. 243)
%k: hour padded (i.e. '1' becomes ' 1'
%l: hour padded (12 hour clock)
%m: month number (1,2,3)
%M: minute (1,2,3,57,58,59)
%n: new line
%N: nanoseconds
%p: AM or PM
%P: like %p but lowercase (ironically)
%r: locales 12 hour clock time
%R: 24 hour version of hour and minute
%s: seconds since 1970-01-01 00:00:00
%S: second (01,02,03, 57, 58, 59)
%t: a tab
%T: time same as %H:%M:%S
%u: day of week (1 is Monday, 2 is Tuesday etc)
%U: week number of year (assuming Sunday as first day of the week)
%V: ISO week number with Monday as the first day of the week
%w: day of week (0 is Sunday)
%W: week number of the year with Monday as the first day of the week
%x: locales date representation (12/31/2015)
%X: locales time representation (14:44:44)
%y: last two digits of year
%Y: year
%z: numeric time zone (i.e. -0400)
%:z: numeric time zone as follows (i.e. -04:00)
%::z: numeric time zone as follows (i.e. -04:00:00)
%Z: alphabetic time zone abbreviation (GMT)
-: a single hyphen prevents zero padding
_: a single underscore pads with spaces
0: pads with zeroes
^: use uppercase if possible
#: use opposite case if possible
To display just the time use the following:
date +%T
Alternatively, use the following:
date +%H:%M:%S
Attach the date, as well, using the command:
date +%d/%m/%Y%t%H:%M:%S
Alternatively, use the follow (since %T is equivalent to %H:%M:%S):
date +$d/%m/%Y%t%T
The : and / characters are optional and can be whatever you want. For example:
date +%dc%mc%Y
outputs: 24c09c2020, if you wanted to use 'c' as a delimiter for some reason.
Use any combination of the above switches after the plus symbol to output the date as you so wish. If you want to add spaces you can use quotes around the date.
date +'%d/%m/%Y %H:%M:%S'
How to Show the UTC Date
View the UTC date for your computer using the following command:
date -u
If you are in the UK you will notice that instead of showing "18:58:20" as the time it will show "17:58:20" as the time.
How to Show the RFC Date
View the RFC date for your computer using the following command:
date --rfc-2822
This displays the date in the following format:
Wed, 20 Apr 2018 19:56:52 +0100
This flag is useful as it shows that you are an hour ahead of GMT.
Some Useful Date Commands
Do you want to know the date next Monday? Try this:
date -d "next Monday"
At the point of writing this returns "Mon 25 Apr 00:00:00 BST 2016"
The -d basically prints a date in the future or the past. So, you can use "next Monday" or "last Friday".
Using the same command you can find out which day of the week your birthday or Christmas falls upon.
date -d 12/25/2016
The result is Sun Dec 25.
Summary
It is worth checking out the manual page for the date command using the following command:
man date
Was this page helpful?
More from Lifewire
Businessman checking the time on his watch
How to Understand the Date and Time in Email Headers
Calendar next to an Apple keyboard
How to Change the Date and Time on a Mac Manually
Turning on automatic date and time settings in Windows 10.
Change the Date and Time Zone on Your Windows Laptop
People comparing the calendars on their iPhones
How to Change Date on iPhone
Woman walking with Black Friday shopping bag
What Is Black Friday?
Clock On White Wall
Find the Sent Timestamp on Gmail Messages
Homescreen with clock on Android
How to Change the Time on Android
Person taking a photo of a flower with a smartphone
How to Adjust the Date, Time, and Location of Photos in iOS 15
Dark office with many computers, one lit up
Understanding the Linux Command: Ar
A human hand pressing an old-fashioned alarm clock
Learn the Linux Command 'at'
Close-Up Of Thumbtack On Calendar Date
Using the DATE Function in Google Sheets
DATE function in Excel
How to Use the Excel DATE Function
Tux the penguin is the official Linux mascot.
Delete Files Using the Linux Command Line
Close-Up Of Clock Against Calendar
Serial Number and Serial Date in Excel
Person running Linux sleep command for 20 seconds on a laptop
How to Use the Linux Sleep Command to Pause a BASH Script
Cropped Hand Of Person Using Laptop By Alarm Clock At Table
Excel's Volatile NOW Function for the Date and Time
Lifewire
Tech for Humans
Follow Us
Subscribe to our newsletter and get techs top stories in 30 seconds.
Email Address
enter email
SUBMIT
News
Best Products
Mobile Phones
Computers
About Us
Advertise
Privacy Policy
Cookie Policy
Careers
Editorial Guidelines
Contact
Terms of Use
EU Privacy
California Privacy Notice
Lifewire is part of the Dotdash publishing family.
</pre>
</html></>
}
RENDER(Request& context)
{
<><html>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Index
</h1>
<? show_stuff(context); ?>
<pre><?= var_dump(context.params) ?></pre>
</html></>
}
+4
View File
@@ -0,0 +1,4 @@
void test_output()
{
print("hello from include!");
}
+57
View File
@@ -0,0 +1,57 @@
RENDER(Request& context)
{
DTree p;
p.set(context.params);
<>
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Index
</h1>
<ul>
<li><a href="../doc/index.uce">Help Docs</a></li>
<li><a href="hello.uce">Hello</a></li>
<li><a href="post.uce">Form Post</a></li>
<li><a href="post-multipart.uce">Form Multipart Post</a></li>
<li><a href="working-dir.uce">Working Directory</a></li>
<li><a href="uri.uce">URI</a></li>
<li><a href="cookie.uce">Cookies</a></li>
<li><a href="session.uce">Session</a></li>
<li><a href="str_replace.uce">String replace</a></li>
<li><a href="dtree.uce">DTree</a></li>
<li><a href="json.uce">JSON</a></li>
<li><a href="memcached.uce">Memcached</a></li>
<li><a href="mysql.uce">MySQL Connector</a></li>
<li><a href="fileio.uce">File I/O</a></li>
<li><a href="shell.uce">Shell</a></li>
<li><a href="file_append.uce">File Append</a></li>
<li><a href="random.uce">RNG/Noise</a></li>
<li><a href="task.uce">Task</a></li>
<li><a href="task_repeat.uce">Task repeat</a></li>
<li><a href="utf8.uce">UTF-8</a></li>
<li><a href="call_file.uce">call_file()</a></li>
<li><a href="parse_time.uce">parse_time()</a></li>
<li><a href="header.uce">header</a></li>
<li><a href="components.uce">Components</a></li>
<li><a href="markdown.uce">Markdown</a></li>
<li><a href="error-reporting.uce">Error reporting</a></li>
<li><a href="websockets.ws.uce">WebSockets</a></li>
</ul>
<pre><?
print("Worker PID: ", my_pid, "\n");
print("Parent PID: ", parent_pid, " \n");
print("Output buffer size: ", context.ob->str().length(), " \n");
print("Request #", context.server->request_count, "\n");
?></pre>
<pre><?= (var_dump(p)) ?></pre>
<div><?
print("Output buffer size: ", context.ob->str().length(), " \n");
?></div>
</>
//context.flags.log_request = false;
}
+56
View File
@@ -0,0 +1,56 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
DTree/JSON
</h1>
JSON:
<pre style="white-space: pre-wrap"><?
t.key("a")->set("valueA");
t.key("b")->set("valueB");
t.key("c")->key("c-dt")->set_bool(true);
t.key("c")->key("c-df")->set_bool(false);
t.key("c")->key("c-e")->set("valueCE");
t.key("c")->key("c-f")->set(&t);
t.key("g")->key("g-h")->key("h-i")->set("valueHI");
t["g"]["x"]["y1"] = "XYZ1";
t["g"]["x"]["y2"] = &t;
t["g"]["x"]["y3"] = time();
t["g"]["x"]["y4"] = "Ünicödä";
t["l"] = context.params;
String j;
print(j = json_encode(t));
?></pre>
Parsed:
<pre><?
print(var_dump(
json_decode(j)
));
?></pre>
Compare:
<pre><?
print(var_dump(
t
));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+36
View File
@@ -0,0 +1,36 @@
# Markdown Demo
This page exercises **strong**, *emphasis*, ~~strikethrough~~, `code spans`, and a bare URL: https://uce.openfu.com/doc/index.uce
## Task List
- [x] Parse markdown into an AST
- [x] Render markdown into HTML
- [ ] Add even more extensions later
## Table
| Feature | Status | Notes |
| :--- | :---: | ---: |
| Headings | Ready | 1 |
| Tables | Ready | 2 |
| Components | Ready | 3 |
## Quote
> Markdown in UCE should be composable.
>
> Components make that much more interesting.
:::warning title="Component-backed directive"
This `:::warning` block is rendered through a normal UCE component selected from `options["components"]`.
:::
## Code
```cpp
RENDER(Request& context)
{
print(markdown_to_html("# hello"));
}
```
+46
View File
@@ -0,0 +1,46 @@
RENDER(Request& context)
{
DTree options;
options["components"][":::warning"] = "components/markdown/warning";
options["components"]["node.code_block"] = "components/markdown/code_block";
String markdown_src = first(
context.post["markdown"],
file_get_contents("markdown-example.md")
);
DTree ast = markdown_to_ast(markdown_src, options);
String html = markdown_to_html(markdown_src, options);
<>
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Markdown
</h1>
<p>
This page exercises `markdown_to_ast()` and `markdown_to_html()` with component hooks for `:::warning` directives and fenced code blocks.
</p>
<form method="post" action="?">
<div>
<section>
<h2>Source</h2>
<textarea name="markdown"><?= markdown_src ?></textarea>
<div>
<input type="submit" value="Render Markdown"/>
</div>
</section>
<section>
<h2>Rendered HTML</h2>
<div>
<?: html ?>
</div>
</section>
</div>
</form>
<details>
<summary>AST JSON</summary>
<pre><?= json_encode(ast) ?></pre>
</details>
</>
}
+40
View File
@@ -0,0 +1,40 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
MemcacheD
</h1>
Stats:
<pre><?
auto sfd = memcache_connect();
print(memcache_command(sfd, "stats"));
?></pre>
Set/Get:
<pre><?
memcache_set(sfd, "test_key", "test_value");
memcache_set(sfd, "test_key2", "test_value2");
print("raw:: "+memcache_command(sfd, "get test_key")+"\n");
print("get:: "+memcache_get(sfd, "test_key")+"\n");
print("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n");
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+51
View File
@@ -0,0 +1,51 @@
RENDER(Request& context)
{
<><html>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
MySQL Connector Test
</h1>
<label>MySQL Connection</label>
<pre><?
String query = "SELECT * FROM :table WHERE x = :val";
StringMap params;
params["table"] = "TableName";
params["val"] = "Dubious\\Value'Name\nwith;breaks";
MySQL con;
if(con.connect("localhost", "root", ""))
{
print("error: "+con.error()+"\n");
print("quotation test: "+con.escape("\"' or 1=1;.")+"\n");
print("query parse: "+con.parse_query_parameters(query, params)+"\n");
print(var_dump(con.query("SHOW DATABASES")));
con.query("USE mysql");
?></pre>
SELECT * FROM user table
<pre><?
print(var_dump(con.query("SELECT * FROM user")));
}
?></pre>
<div><?
print("connection status: ", con.statement_info, "\n");
?></div>
<label>CGI Params</label>
<pre><?= var_dump(context.params) ?></pre>
</html></>
}
+30
View File
@@ -0,0 +1,30 @@
RENDER(Request& context)
{
String raw = first(context.post["raw"], "today");
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
parse_time
</h1>
<form action="?" method="post">
<div>
<label>Time string</label>
<input type="text" name="raw" value="<?= raw ?>"/>
</div>
<div>
<input type="submit" value="Parse"/>
</div>
</form>
<pre><?
print(date("%Y-%m-%d %H:%M", parse_time(raw)));
?></pre>
<pre><?= var_dump(context.params) ?></pre>
</>
}
+47
View File
@@ -0,0 +1,47 @@
void show_form(Request& context)
{
<><form action="?" method="post" enctype="multipart/form-data">
<div>
<label>Some text:</label>
<input type="text" name="fühld" value="<?= context.post["fühld"] ?>"/>
</div>
<div>
<label>Some multiline text:</label>
<textarea name="field2"><?= context.post["field2"] ?></textarea>
</div>
<div>
<input type="submit" value="Submit Form"/>
</div>
</form></>
}
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Multipart-Encoded Form POST
</h1>
<? show_form(context); ?>
<div>
</div>
<label>Parsed POST fields</label>
<pre><?= var_dump(context.post) ?></pre>
<label>Raw POST content</label>
<pre><?= context.in ?></pre>
<label>CGI Params</label>
<pre><?= var_dump(context.params) ?></pre>
</>
}
+43
View File
@@ -0,0 +1,43 @@
EXPORT void show_form(Request& context)
{
<><form action="?" method="post">
<div>
<label>Some text:</label>
<input type="text" name="field" value="<?= context.post["field"] ?>"/>
</div>
<div>
<label>Some multiline text:</label>
<textarea name="field2"><?= context.post["field2"] ?></textarea>
</div>
<div>
<input type="submit" value="Submit Form"/>
</div>
</form></>
}
RENDER(Request& context)
{
<><html>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Form POST
</h1>
<? show_form(context); ?>
<label>Parsed POST fields</label>
<pre><?= var_dump(context.post) ?></pre>
<label>Raw POST content</label>
<pre><?= context.in ?></pre>
<label>CGI Params</label>
<pre><?= var_dump(context.params) ?></pre>
</html></>
}
+49
View File
@@ -0,0 +1,49 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Random
</h1>
</>
<>
Generate Some Numbers
<pre><?
u64 max_64 = 0xffffffffffffffff;
u64 max_32 = 0xffffffff;
for(auto i = 0; i < 100; i++)
{
print(i, ": ", (float)gen_noise32(i)/(float)max_32, " / ", (float)gen_noise64(i)/(float)max_64, " / ", gen_noise01(i), " / ",
gen_int(0, 4, i), " / ", gen_float(0.0, 4.0, i), "\n");
}
?></pre>
Draw Some Numbers
<div>
Seed <?= context.random_seed ?>
</div>
<pre><?
for(auto i = 0; i < 100; i++)
{
print(i, ": ", draw_int(0, 4), " / ", draw_float(0.0, 4.0), "\n");
}
?></pre>
<div>
Sha1 of '1234': <?= gen_sha1("1234") ?>
</div>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+17
View File
@@ -0,0 +1,17 @@
v1 : string = "";
v2 := 'BLA';
i1 := 123.2;
for(v3 => c)
print(c);
v1 = "This is an interpolated string {=i1}
which also contains line breaks";
?><div>
It's now time for some HTML!
</div>
<?
print("And, we're back!");
+1
View File
@@ -0,0 +1 @@
+143
View File
@@ -0,0 +1,143 @@
enum TokenType{ TT_UNKNOWN, TT_STRING, TT_INT, TT_FLOAT, TT_IDENTIFIER, TT_OPERATOR };
String TokenTypeName[] = { "TT_UNKNOWN", "TT_STRING", "TT_INT", "TT_FLOAT", "TT_IDENTIFIER", "TT_OPERATOR" };
struct Token
{
String literal = "";
TokenType type = TT_UNKNOWN;
char delim = ' ';
};
#define NEW_TOKEN { result.push_back(ctok); ctok = new Token(); goto eval_char; }
std::vector<Token*> script_tokenize(String code)
{
std::vector<Token*> result;
auto ctok = new Token();
for(auto c : code)
{
eval_char:
if(ctok->type == TT_UNKNOWN)
{
if(isspace(c))
{
}
else if(isdigit(c))
{
ctok->type = TT_INT;
}
else if(isalpha(c))
{
ctok->type = TT_IDENTIFIER;
}
else if(c == '"' || c == '\'')
{
ctok->type = TT_STRING;
ctok->delim = c;
continue;
}
else if(ispunct(c))
{
ctok->type = TT_OPERATOR;
}
}
switch(ctok->type)
{
case(TT_IDENTIFIER):
{
if(isalnum(c) || c == '_')
ctok->literal += c;
else
NEW_TOKEN
break;
}
case(TT_INT):
{
if(isdigit(c))
ctok->literal += c;
else if(c == '.')
{
ctok->type = TT_FLOAT;
ctok->literal += c;
}
else
NEW_TOKEN
break;
}
case(TT_FLOAT):
{
if(isdigit(c))
ctok->literal += c;
else
NEW_TOKEN
break;
}
case(TT_OPERATOR):
{
ctok->literal += c;
c = ' ';
NEW_TOKEN
break;
}
case(TT_STRING):
{
if(c == ctok->delim)
{
c = ' ';
NEW_TOKEN
}
else
ctok->literal += c;
break;
}
}
}
result.push_back(ctok);
return(result);
}
String to_string(std::vector<Token*> t)
{
String result = "";
for(auto& ti : t)
{
result += concat(TokenTypeName[ti->type], "(", ti->literal, ") ");
}
return(result);
}
// "
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Script
</h1>
</>
String script_src = first(context.post["code"], file_get_contents("script-example1.usp"));
<>
<h3>Code</h3>
<form action="?" method="post">
<textarea name="code"><?= script_src ?></textarea>
<input type="submit" value="parse"/>
</form>
<pre><?
auto tokens = script_tokenize(script_src);
print(html_escape(to_string(tokens)));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+52
View File
@@ -0,0 +1,52 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Session
</h1>
</>
String action = context.get["action"];
if(context.cookies["uce-session"].length() > 0)
session_start();
if(action == "start")
{
session_start();
print("action: starting session");
}
else if(action == "store")
{
context.session["stored-value"] = make_session_id();
print("action: storing value "+context.session["stored-value"]);
}
else if(action == "destroy")
{
session_destroy();
print("action: destroying session");
}
<>
<br/>
<a href="?action=start" class="button">Start Session</a> |
<a href="?" class="button">Refresh</a> |
<a href="?action=destroy" class="button">Destroy Session</a> |
<a href="?action=store" class="button">Store Value</a> |
Info
<pre><?
print(var_dump(context.cookies));
print("SESSION:\n");
print(var_dump(context.session));
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+7
View File
@@ -0,0 +1,7 @@
RENDER(Request& context)
{
auto p = compiler_load_shared_unit(context, "post.uce");
if(p)
print(to_string(p));
}
+40
View File
@@ -0,0 +1,40 @@
RENDER(Request& context)
{
<><html>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Shell Stuff
</h1>
<div>shell_exec()</div>
<pre><?
print(shell_exec("ls -l"));
?></pre>
<div>shell_escape()</div>
<pre style="height:80px"><?
print(shell_exec("echo "+shell_escape("kasjdf 1ölkasj öflkjasdö\\lkfjsöa'ldkfj 23487692\"bla83746")));
?></pre>
<div>Git</div>
<pre><?
print(shell_exec("git show"));
?></pre>
<pre><?= var_dump(context.params) ?></pre>
</html></>
}
+33
View File
@@ -0,0 +1,33 @@
void str_replace_test(String s, String sr, String rp)
{
print("in '", s, "' replace all '", sr, "' with '", rp, "' =&gt; ");
print(replace(s, sr, rp));
}
RENDER(Request& context)
{
<><html>
<link rel="stylesheet" href='style.css?v=1'></link>
<h1>
<a href="index.uce">UCE Test</a>:
String Replace
</h1>
<div>
<? str_replace_test("abcdefgh", "c", "C"); ?>
</div>
<div>
<? str_replace_test("abcccdefgh", "c", "C"); ?>
</div>
<div>
<? str_replace_test("abcccdefgh", "ccc", "C"); ?>
</div>
<pre><?= var_dump(context.params) ?></pre>
</html></>
}
+27
View File
@@ -0,0 +1,27 @@
RENDER(Request& context)
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Strings
</h1>
<pre style="white-space: pre-wrap"><?
print(String("!") + 60*60*24);
?></pre>
Params
<pre><?= var_dump(context.params) ?></pre>
</>
}
+82
View File
@@ -0,0 +1,82 @@
* {
font-family: inherit;
font-size: inherit;
box-sizing: inherit;
color: inherit;
line-height: inherit;
}
a {
color: yellow;
}
h1 {
font-size: 200%;
padding-top: 8px;
padding-bottom: 8px;
font-family: monospace;
}
body {
max-width: 1024px;
margin-left: auto;
margin-right: auto;
padding-left: 16px;
padding-right: 16px;
font-family: Tahoma, Helvetica, Arial;
font-size: 1.2em;
box-sizing: border-box;
background: #139;
color: white;
line-height: 150%;
}
body > * {
background: rgba(255,255,255,0.1);
padding: 32px;
margin: 16px;
}
form > div, label {
display: block;
padding-top: 8px;
padding-bottom: 8px;
}
input, textarea {
background: rgba(0,0,0,0.2);
border: 2px solid rgba(255,255,255,0.2);
}
input[type=submit], button {
padding: 8px;
cursor: pointer;
}
input[type=submit]:hover, button:hover {
color: yellow;
background: rgba(0,0,0,0.5);
}
input[type=text], textarea {
padding: 8px;
width: 100%;
}
input[type=text]:hover, textarea:hover {
background: rgba(0,0,0,0.25);
}
textarea {
height: 20%;
}
pre {
height: 20%;
overflow: auto;
padding: 8px;
border: 2px solid rgba(0,0,0,0.2);
background: rgba(255,255,255,0.1);
font-family: monospace;
white-space: pre-wrap;
}
+9
View File
@@ -0,0 +1,9 @@
RENDER(Request& context)
{
String task_name = first(context.get["task-name"], "example-task");
print("Task Name: ", task_name, "\n");
print("Task ID: ", task_pid(task_name), "\n");
print("Task Running: ", task_pid(task_name) == 0 ? "no" : "yes", "\n");
}
+80
View File
@@ -0,0 +1,80 @@
RENDER(Request& context)
{
DTree t;
String task_name = first(context.get["task-name"], "example-task");
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Tasks
</h1>
<script>
function load(target, url) {
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
target.innerHTML = r.responseText;
};
r.send();
}
</script>
<form action="?">
Task name
<input type="text" name="task-name" value="<?= task_name ?>"/>
<input type="submit" name="cmd" value="Get Info"/>
<input type="submit" name="cmd" value="Execute"/>
</form>
<script>
/*setInterval(() => {
load(document.getElementById('task-status'), 'task-status.uce?task-name=<?= uri_encode(task_name) ?>');
}, 200);*/
</script>
Task Status
<pre id="task-status" style="white-space: pre-wrap"><?
print("Task Name: ", task_name, "\n");
print("Task ID: ", task_pid(task_name), "\n");
print("Task Running: ", task_pid(task_name) == 0 ? "no" : "yes", "\n");
?></pre>
<?
if(context.get["cmd"] == "Execute")
{
?>
Task Start
<pre style="white-space: pre-wrap"><?
print("New Task ID: ", task("example-task", []() {
sleep(10);
}), "\n");
print("Task run time: 10 seconds");
?></pre><?
}
?>
Params
<pre><?= var_dump(context.get) ?></pre>
</>
}
+80
View File
@@ -0,0 +1,80 @@
RENDER(Request& context)
{
DTree t;
String task_name = first(context.get["task-name"], "example-task");
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Task repeat
</h1>
<script>
function load(target, url) {
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
target.innerHTML = r.responseText;
};
r.send();
}
</script>
<form action="?">
Task name
<input type="text" name="task-name" value="<?= task_name ?>"/>
<input type="submit" name="cmd" value="Get Info"/>
<input type="submit" name="cmd" value="Execute"/>
</form>
<script>
/*setInterval(() => {
load(document.getElementById('task-status'), 'task-status.uce?task-name=<?= uri_encode(task_name) ?>');
}, 200);*/
</script>
Task Status
<pre id="task-status" style="white-space: pre-wrap"><?
print("Task Name: ", task_name, "\n");
print("Task ID: ", task_pid(task_name), "\n");
print("Task Running: ", task_pid(task_name) == 0 ? "no" : "yes", "\n");
?></pre>
<?
if(context.get["cmd"] == "Execute")
{
?>
Task Start
<pre style="white-space: pre-wrap"><?
print("New Task ID: ", task_repeat("example-task", 5, []() {
sleep(1);
}), "\n");
print("Task interval: 5 seconds");
?></pre><?
}
?>
Params
<pre><?= var_dump(context.get) ?></pre>
</>
}
+6
View File
@@ -0,0 +1,6 @@
RENDER(Request& context)
{
print("Sub-Invoke Working dir: ", get_cwd(), "\n");
}
+28
View File
@@ -0,0 +1,28 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
URI
</h1>
<form action="?" method="post">
<div>
<label>uri_encode</label>
<input type="text" name="uri_encode" value="<?= context.post["uri_encode"] ?>"/>
<br/>
Encode: <?= uri_encode(context.post["uri_encode"]) ?>
<br/>
Decode: <?= uri_decode(uri_encode(context.post["uri_encode"])) ?>
</div>
<div>
<input type="submit" value="Submit Form"/>
</div>
</form>
<pre><?= var_dump(context.params) ?></pre>
</>
}
+61
View File
@@ -0,0 +1,61 @@
String string_to_hex(String s)
{
String result = "";
for(auto c : s)
{
result += to_hex(c);
}
return(result);
}
RENDER(Request& context)
{
String raw = first(context.post["raw"], "■👪▧▲🏳️‍🌈😂👋🏽😆😏😱🇦🇽Udø島リZ̸̢̧̡̧̗̰̪͉̤͖͉̪̝̦͎̮̑͜a̸̧̝̱̹̲̗̪̰̦͒̃͋̿̿̃̈͑̐͑͗̚̕̚͝͠l͚̜͕̠̣ģ̸̧̘̜͇͚͈͙̓̌̅͑͊͊͋̓́͌̈́̿̈́͗͘̚ͅͅȏ̶̗̤̳͎̫̥͕̣͔̥̙̜̰̂͌̍͊͂́̅̇̒̕̕ルイ社もなく");
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
UTF-8
</h1>
<form action="?" method="post">
<div>
<label>split_utf8</label>
<input type="text" name="raw" value="<?= raw ?>"/>
</div>
<div>
<input type="submit" value="Submit Form"/>
</div>
</form>
Simple Characters
<pre><?
u32 item_idx = 0;
for(auto seg : split_utf8(raw))
{
item_idx++;
print(string_to_hex(seg), " ", seg, "\t");
if(item_idx % 4 == 0)
print("\n");
}
?></pre>
Compound Characters
<pre><?
item_idx = 0;
for(auto seg : split_utf8(raw, true))
{
item_idx++;
print(string_to_hex(seg), " ", seg, "\t");
if(item_idx % 4 == 0)
print("\n");
}
?></pre>
<pre><?= var_dump(context.params) ?></pre>
</>
}
+195
View File
@@ -0,0 +1,195 @@
String clean_chat_field(String raw, u32 max_length)
{
String value = trim(raw);
value = replace(value, "\r", " ");
value = replace(value, "\n", " ");
if(value.length() > max_length)
value.resize(max_length);
return(value);
}
DTree chat_event(Request& context, String type, String body)
{
DTree event;
event["type"] = type;
event["body"] = body;
event["connection_id"] = ws_connection_id();
event["scope"] = first(context.params["DOCUMENT_URI"], ws_scope());
event["online"] = (f64)ws_connection_count();
event["at"] = gmdate("%H:%M:%S");
event["name"] = context.connection["name"].to_string();
event["message_count"] = context.connection["message_count"];
return(event);
}
RENDER(Request& context)
{
String ws_url = context.params["DOCUMENT_URI"];
u64 online = ws_connection_count();
<>
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
<h1>
<a href="index.uce">UCE Test</a>:
WebSocket Chat
</h1>
<label>Chat Info</label>
<pre>Page scope: <?= ws_url ?>
Connected right now: <span id="online-count"><?= online ?></span>
Status: <span id="status">Connecting...</span></pre>
<form id="chat-form" action="?" method="post">
<div>
<label>Display name:</label>
<input id="chat-name" type="text" maxlength="32" value="guest-<?= draw_int(1000, 9999) ?>"/>
</div>
<div>
<label>Message:</label>
<textarea id="chat-message" maxlength="500" placeholder="Say something to everyone connected to this same .ws.uce page"></textarea>
</div>
<div>
<input id="send-button" type="submit" value="Send Message"/>
</div>
</form>
<label>Chat Log</label>
<pre id="chat-log"></pre>
<script>
const wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}<?= ws_url ?>`;
const statusEl = document.getElementById('status');
const onlineEl = document.getElementById('online-count');
const logEl = document.getElementById('chat-log');
const formEl = document.getElementById('chat-form');
const nameEl = document.getElementById('chat-name');
const messageEl = document.getElementById('chat-message');
const sendButtonEl = document.getElementById('send-button');
const savedName = window.localStorage.getItem('uce-chat-name');
if (savedName) nameEl.value = savedName;
let ws;
let reconnectDelay = 1000;
function addLine(kind, title, body, meta = '') {
const prefix = kind === 'system' ? '[system]' : `[${title}]`;
const metaText = meta ? ` ${meta}` : '';
logEl.append(`${prefix} ${body}${metaText}\n`);
logEl.scrollTop = logEl.scrollHeight;
}
function setStatus(text, online) {
statusEl.textContent = text;
if (typeof online === 'number') onlineEl.textContent = String(online);
}
function sendPayload(payload) {
if (!ws || ws.readyState !== WebSocket.OPEN) return false;
payload.name = (nameEl.value || '').trim().slice(0, 32) || 'guest';
window.localStorage.setItem('uce-chat-name', payload.name);
ws.send(JSON.stringify(payload));
return true;
}
function connect() {
ws = new WebSocket(wsUrl);
setStatus(`Connecting to ${wsUrl}...`);
sendButtonEl.disabled = true;
ws.addEventListener('open', () => {
reconnectDelay = 1000;
sendButtonEl.disabled = false;
setStatus('Connected');
addLine('system', 'system', 'socket connected', new Date().toLocaleTimeString());
sendPayload({ type: 'join' });
});
ws.addEventListener('message', (event) => {
let payload;
try {
payload = JSON.parse(event.data);
} catch (error) {
addLine('system', 'decode error', String(error), new Date().toLocaleTimeString());
return;
}
if (typeof payload.online === 'number') onlineEl.textContent = String(payload.online);
if (payload.type === 'message') {
addLine('', payload.name || 'guest', payload.body || '', `${payload.at || ''} ${payload.connection_id || ''}`);
} else {
addLine('system', payload.type || 'system', payload.body || '', `${payload.at || ''} ${payload.connection_id || ''}`);
}
});
ws.addEventListener('close', () => {
sendButtonEl.disabled = true;
setStatus(`Disconnected, retrying in ${reconnectDelay / 1000}s`);
addLine('system', 'system', 'socket closed', new Date().toLocaleTimeString());
window.setTimeout(connect, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, 10000);
});
ws.addEventListener('error', () => {
setStatus('WebSocket error');
});
}
formEl.addEventListener('submit', (event) => {
event.preventDefault();
const body = (messageEl.value || '').trim();
if (!body) return;
if (sendPayload({ type: 'message', body })) {
messageEl.value = '';
messageEl.focus();
}
});
connect();
</script>
</>
}
WS(Request& context)
{
if(ws_is_binary())
{
ws_send_to(
ws_connection_id(),
json_encode(chat_event(context, "notice", "Binary messages are not handled by this demo"))
);
return;
}
DTree payload = json_decode(ws_message());
String type = clean_chat_field(payload["type"].to_string(), 24);
String name = clean_chat_field(payload["name"].to_string(), 32);
String body = clean_chat_field(payload["body"].to_string(), 500);
u64 message_count = int_val(context.connection["message_count"].to_string());
if(name == "")
name = first(context.connection["name"].to_string(), "guest");
context.connection["name"] = name;
if(type == "join")
{
context.connection["joined_at"] = gmdate("%Y-%m-%d %H:%M:%S");
context.connection["last_type"] = type;
ws_send(json_encode(chat_event(context, "join", name + " joined the room")));
return;
}
if(type == "message" && body != "")
{
context.connection["last_type"] = type;
context.connection["last_body"] = body;
context.connection["message_count"] = (f64)(message_count + 1);
DTree event = chat_event(context, "message", body);
ws_send(json_encode(event));
return;
}
if(type != "")
{
context.connection["last_type"] = type;
ws_send_to(ws_connection_id(), json_encode(chat_event(context, "notice", "Unknown message type: " + type)));
}
}
+19
View File
@@ -0,0 +1,19 @@
RENDER(Request& context)
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Working Directory
</h1>
<pre><?
print("Base WD: " + get_cwd() + "\n");
render_file("test2/working-dir-test.uce", context);
?></pre>
<pre><?= var_dump(context.params) ?></pre>
</>
}