(&request.stats.time_start));
+ request.ob_start();
+
+ if(request.params["HTTP_COOKIE"].length() > 0)
+ request.cookies = parse_cookies(request.params["HTTP_COOKIE"]);
+
+ String ct_info = request.params["CONTENT_TYPE"];
+ String ct_type = nibble(";", ct_info);
+
+ if(request.params["REQUEST_METHOD"] == "POST")
+ {
+ if(ct_type == "multipart/form-data")
+ {
+ nibble("boundary=", ct_info);
+ request.post = parse_multipart(request.in, String("--")+ct_info, request.uploaded_files);
+ }
+ else
+ {
+ request.post = parse_query(request.in);
+ }
+ }
+
+ // printf("(i) request ready\n");
+ request.invoke(request.params["SCRIPT_FILENAME"]);
+
+ for( auto &f : request.uploaded_files)
+ {
+ unlink(f.tmp_name);
+ }
+
+ if(request.session_id.length() > 0)
+ save_session_data(request.session_id, request.session);
+
+ cleanup_mysql_connections();
+
+ return 0;
+}
+
+void listen_for_connections()
+{
+ signal(SIGSEGV, on_segfault);
+ server.on_request = &handle_request;
+ server.on_data = &handle_data;
+ server.on_complete = &handle_complete;
+ /*
+ server.request_handler(&handle_request);
+ server.data_handler(&handle_data);
+ server.complete_handler(&handle_complete);
+ */
+ for(;;)
+ {
+ //if(request_arena) request_arena->clear();
+ //current_memory_arena = request_arena;
+ server.process();
+ }
+}
+
+int main(int argc, char** argv)
+{
+ printf("(P) Starting parent server PID:%i\n", getpid());
+
+ signal(SIGCHLD, on_child_exit);
+ srand(time());
+
+ //if(server_state.config.COMPILER_SYS_PATH == "")
+ server_state.config.COMPILER_SYS_PATH = get_cwd();
+
+ // printf("MySQL client version: %s\n", mysql_get_client_info());
+
+ printf("Compiler base path: %s\n", server_state.config.COMPILER_SYS_PATH.c_str());
+
+ server_state.config.COMPILE_SCRIPT =
+ server_state.config.COMPILER_SYS_PATH + "/" + server_state.config.COMPILE_SCRIPT;
+ if(server_state.config.LISTEN_PORT)
+ server.listen(server_state.config.LISTEN_PORT);
+ if(server_state.config.SOCKET_PATH != "")
+ server.listen(server_state.config.SOCKET_PATH);
+ chmod(server_state.config.SOCKET_PATH.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+ dirname(server_state.config.COMPILER_SYS_PATH);
+ basename(server_state.config.COMPILER_SYS_PATH);
+
+ mkdir(server_state.config.BIN_DIRECTORY);
+ mkdir(server_state.config.TMP_UPLOAD_PATH);
+ mkdir(server_state.config.SESSION_PATH);
+
+ //server.process(100);
+ //server.process();
+ /*try
+ {
+ server.process_forever();
+ }
+ catch (const std::runtime_error& e)
+ {
+ std::cout << e.what();
+ }*/
+
+ for(;;)
+ {
+ while(workers.size() < server_state.config.WORKER_COUNT)
+ {
+ spawn_subprocess(listen_for_connections);
+ }
+ sleep(1);
+ }
+
+ return 0;
+}
diff --git a/start.sh b/start.sh
new file mode 100755
index 0000000..1c10d67
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -r /tmp/uce/work/* ; ./build_linux.sh && bin/uce_fastcgi.debug.linux.bin
diff --git a/test/.fuse_hidden000003060000000a b/test/.fuse_hidden000003060000000a
new file mode 100644
index 0000000..e69de29
diff --git a/test/.fuse_hidden000003150000000b b/test/.fuse_hidden000003150000000b
new file mode 100644
index 0000000..e69de29
diff --git a/test/.fuse_hidden000003310000000c b/test/.fuse_hidden000003310000000c
new file mode 100644
index 0000000..e69de29
diff --git a/test/.fuse_hidden000003d000000010 b/test/.fuse_hidden000003d000000010
new file mode 100644
index 0000000..e69de29
diff --git a/test/cookie.uce b/test/cookie.uce
new file mode 100644
index 0000000..b898cb5
--- /dev/null
+++ b/test/cookie.uce
@@ -0,0 +1,30 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+ Set
+
+
+ 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));
+
+ ?>
+ Get
+
+
+ print(var_dump(context->cookies));
+
+ ?>
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/dtree.uce b/test/dtree.uce
new file mode 100644
index 0000000..97a7ff4
--- /dev/null
+++ b/test/dtree.uce
@@ -0,0 +1,54 @@
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+
+ Value Types:
+
+
+
+ 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");
+
+ ?>
+
+ Tree:
+
+
+
+ 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));
+
+ ?>
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/empty.uce b/test/empty.uce
new file mode 100644
index 0000000..7d604e4
--- /dev/null
+++ b/test/empty.uce
@@ -0,0 +1,4 @@
+void hello()
+{
+
+}
diff --git a/test/file_append.uce b/test/file_append.uce
new file mode 100644
index 0000000..c9adf67
--- /dev/null
+++ b/test/file_append.uce
@@ -0,0 +1,36 @@
+
+
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+ UCE Test:
+ File Append
+
+
+ File Append:
+
+
+
+ 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"));
+
+ ?>
+
+
+
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/fileio.uce b/test/fileio.uce
new file mode 100644
index 0000000..69474bc
--- /dev/null
+++ b/test/fileio.uce
@@ -0,0 +1,22 @@
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+
+ File IO:
+
+ = file_get_contents("fileio.uce") ?>
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/hello.uce b/test/hello.uce
new file mode 100644
index 0000000..e29732d
--- /dev/null
+++ b/test/hello.uce
@@ -0,0 +1,189 @@
+
+
+void show_stuff()
+{
+ //context->header["Content-Type"] = "text/plain";
+
+ <>
+ Mwahahaaha = time() ?>
+ hello world: = context->params["HTTP_HOST"] ?>
+
+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 tech’s 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.
+
+
+ >
+
+}
+
+RENDER()
+{
+
+ <>
+
+
+ show_stuff(); ?>
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/inc-test.cpp b/test/inc-test.cpp
new file mode 100644
index 0000000..4550c6c
--- /dev/null
+++ b/test/inc-test.cpp
@@ -0,0 +1,4 @@
+void test_output()
+{
+ print("hello from include!");
+}
diff --git a/test/index.uce b/test/index.uce
new file mode 100644
index 0000000..4270828
--- /dev/null
+++ b/test/index.uce
@@ -0,0 +1,46 @@
+
+
+RENDER()
+{
+ DTree p;
+ p.set(context->params);
+
+ <>
+
+
+
+
+ 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");
+ ?>
+ = (var_dump(p)) ?>
+
+ print("Output buffer size: ", context->ob->str().length(), " \n");
+ ?>
+ >
+
+ //context->flags.log_request = false;
+
+}
diff --git a/test/json.uce b/test/json.uce
new file mode 100644
index 0000000..3110f7e
--- /dev/null
+++ b/test/json.uce
@@ -0,0 +1,56 @@
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+ UCE Test:
+ DTree/JSON
+
+
+ JSON:
+
+
+
+ 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));
+
+ ?>
+
+ Parsed:
+
+
+ print(var_dump(
+ json_decode(j)
+ ));
+ ?>
+
+ Compare:
+
+
+ print(var_dump(
+ t
+ ));
+ ?>
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/memcached.uce b/test/memcached.uce
new file mode 100644
index 0000000..db8465b
--- /dev/null
+++ b/test/memcached.uce
@@ -0,0 +1,40 @@
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+ UCE Test:
+ MemcacheD
+
+
+ Stats:
+
+
+
+ auto sfd = memcache_connect();
+
+ print(memcache_command(sfd, "stats"));
+
+ ?>
+
+ Set/Get:
+
+
+
+ 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");
+
+ ?>
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/mysql.uce b/test/mysql.uce
new file mode 100644
index 0000000..8ca7043
--- /dev/null
+++ b/test/mysql.uce
@@ -0,0 +1,51 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+ UCE Test:
+ MySQL Connector Test
+
+
+
+
+
+ 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");
+
+ ?>
+
+ SELECT * FROM user table
+
+
+
+ print(var_dump(con.query("SELECT * FROM user")));
+
+ }
+
+
+ ?>
+
+
+ print("connection status: ", con.statement_info, "\n");
+ ?>
+
+
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/post-multipart.uce b/test/post-multipart.uce
new file mode 100644
index 0000000..a640a6b
--- /dev/null
+++ b/test/post-multipart.uce
@@ -0,0 +1,47 @@
+
+void show_form()
+{
+
+ <>>
+
+}
+
+RENDER()
+{
+
+ <>
+
+
+ UCE Test:
+ Multipart-Encoded Form POST
+
+
+ show_form(); ?>
+
+
+
+
+
+
+ = var_dump(context->post) ?>
+
+
+ = context->in ?>
+
+
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/post.uce b/test/post.uce
new file mode 100644
index 0000000..fc85293
--- /dev/null
+++ b/test/post.uce
@@ -0,0 +1,43 @@
+
+void show_form()
+{
+
+ <>>
+
+}
+
+RENDER()
+{
+
+ <>
+
+
+ UCE Test:
+ Form POST
+
+
+ show_form(); ?>
+
+
+ = var_dump(context->post) ?>
+
+
+ = context->in ?>
+
+
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/random.uce b/test/random.uce
new file mode 100644
index 0000000..ea92559
--- /dev/null
+++ b/test/random.uce
@@ -0,0 +1,49 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+ >
+
+ <>
+ Generate Some Numbers
+
+
+ u64 max_64 = 0xffffffffffffffff;
+ u64 max_32 = 0xffffffff;
+
+ for(auto i = 0; i < 100; i++)
+ {
+ print(i, ": ", (float)noise32(i)/(float)max_32, " / ", (float)noise64(i)/(float)max_64, " / ", noise01(i), " / ",
+ generate_int(0, 4, i), " / ", generate_float(0.0, 4.0, i), "\n");
+ }
+
+ ?>
+ Draw Some Numbers
+
+ Seed = context->random_seed ?>
+
+
+
+ for(auto i = 0; i < 100; i++)
+ {
+ print(i, ": ", draw_int(0, 4), " / ", draw_float(0.0, 4.0), "\n");
+ }
+
+ ?>
+
+
+ Sha1 of '1234': = sha1("1234") ?>
+
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/session.uce b/test/session.uce
new file mode 100644
index 0000000..fa46e62
--- /dev/null
+++ b/test/session.uce
@@ -0,0 +1,52 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+ >
+
+
+ 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");
+ }
+
+ <>
+
+ Start Session |
+ Refresh |
+ Destroy Session |
+ Store Value |
+ Info
+
+
+ print(var_dump(context->cookies));
+ print("SESSION:\n");
+ print(var_dump(context->session));
+
+ ?>
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/string.uce b/test/string.uce
new file mode 100644
index 0000000..80b00ef
--- /dev/null
+++ b/test/string.uce
@@ -0,0 +1,27 @@
+
+
+
+
+
+RENDER()
+{
+ DTree t;
+
+ <>
+
+
+
+
+
+ print(String("!") + 60*60*24);
+
+ ?>
+
+ Params
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/style.css b/test/style.css
new file mode 100644
index 0000000..1ac1b4f
--- /dev/null
+++ b/test/style.css
@@ -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;
+}
diff --git a/test/task-status.uce b/test/task-status.uce
new file mode 100644
index 0000000..4891132
--- /dev/null
+++ b/test/task-status.uce
@@ -0,0 +1,9 @@
+
+RENDER()
+{
+ 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");
+}
diff --git a/test/task.uce b/test/task.uce
new file mode 100644
index 0000000..ad9d129
--- /dev/null
+++ b/test/task.uce
@@ -0,0 +1,80 @@
+
+RENDER()
+{
+ DTree t;
+
+ String task_name = first(context->get["task-name"], "example-task");
+
+ <>
+
+
+
+
+
+
+
+
+
+ Task Status
+
+
+
+ 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");
+
+
+ ?>
+
+
+ if(context->get["cmd"] == "Execute")
+ {
+ ?>
+ Task Start
+
+
+
+ print("New Task ID: ", task("example-task", []() {
+
+ sleep(10);
+
+ }), "\n");
+
+ print("Task run time: 10 seconds");
+
+ ?>
+ }
+ ?>
+
+ Params
+ = var_dump(context->get) ?>
+ >
+
+}
diff --git a/test/test2/.fuse_hidden0000027900000008 b/test/test2/.fuse_hidden0000027900000008
new file mode 100644
index 0000000..e69de29
diff --git a/test/test2/working-dir-test.uce b/test/test2/working-dir-test.uce
new file mode 100644
index 0000000..c5b3a27
--- /dev/null
+++ b/test/test2/working-dir-test.uce
@@ -0,0 +1,6 @@
+
+
+RENDER()
+{
+ print("Sub-Invoke Working dir: ", get_cwd(), "\n");
+}
diff --git a/test/uri.uce b/test/uri.uce
new file mode 100644
index 0000000..f46c890
--- /dev/null
+++ b/test/uri.uce
@@ -0,0 +1,28 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+
+ = var_dump(context->params) ?>
+ >
+
+}
diff --git a/test/working-dir.uce b/test/working-dir.uce
new file mode 100644
index 0000000..6322d3d
--- /dev/null
+++ b/test/working-dir.uce
@@ -0,0 +1,20 @@
+
+
+RENDER()
+{
+
+ <>
+
+
+ UCE Test:
+ Working Directory
+
+
+ print("Base WD: " + get_cwd() + "\n");
+ context->invoke("test2/working-dir-test.uce");
+ ?>
+ = var_dump(context->params) ?>
+ >
+
+}
+
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 0000000..1f8243d
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,38 @@
+Library
+=================================
+- md5 / meow
+- fold StringList into DTree _OR_ make better StringList
+- make session data use DTree instead of StringList
+
+Bugs
+=================================
+- shell_escape()
+
+
+Framework
+=================================
+- Check: File Upload
+- Proxy mode
+- WebSockets
+- Resident code / Cron / Tick?
+- Automated Test Suite
+- Documentation
+
+
+Performance
+=================================
+- Arena Allocator
+- Array implementation
+
+
+Nice to Have
+=================================
+- pseudorandom
+- XML components
+- Optionally store compiled units alongside source
+
+
+Finally
+=================================
+- DO WE DO OUR OWN LANGUAGE OR DO WE KEEP USING C?!?
+