sub-invoke()

This commit is contained in:
Udo 2021-10-29 14:17:00 +00:00
parent a65a3d1207
commit fa432a0482
14 changed files with 196 additions and 87 deletions

Binary file not shown.

View File

@ -16,14 +16,13 @@ mkdir bin/assets > /dev/null 2>&1
mkdir work > /dev/null 2>&1
COMPILER="clang++"
FLAGS="-w -Wall -$OPT_FLAG -std=c++17 -fpermissive -ffast-math"
FLAGS="-g -w -Wall -$OPT_FLAG -std=c++17 -fpermissive -ffast-math"
LIBS="-ldl -lm -lpthread "
SRCFLAGS="-D EXEC_NAME=\"$GF\" -D PLATFORM_NAME=\"linux\""
echo "Compliling executable..."
#time -p
$COMPILER src/linux_fastcgi.cpp $SRCFLAGS $FLAGS $LIBS -o bin/$GF.$BUILDMODE.linux.bin 2>&1
time -p $COMPILER src/linux_fastcgi.cpp $SRCFLAGS $FLAGS $LIBS -o bin/$GF.$BUILDMODE.linux.bin 2>&1
if [ $? -eq 0 ]
then

View File

@ -1,31 +1,6 @@
#include <dlfcn.h>
#define RENDER() extern "C" void render()
typedef void (*call_handler)();
typedef void (*request_handler)(Request* request);
struct SharedUnit {
string file_name;
string so_name;
void* so_handle;
request_handler on_setup;
call_handler on_render;
string compiler_messages;
time_t last_compiled;
~SharedUnit()
{
if(so_handle)
{
dlclose(so_handle);
}
}
};
std::map<string, SharedUnit*> units;
string process_html_literal(string content, string file_name)
string process_html_literal(SharedUnit* su, string content)
{
string pc;
string HT_START = "context->print(R\"(";
@ -99,9 +74,10 @@ string process_html_literal(string content, string file_name)
return(HT_START + pc + HT_END);
}
string preprocess(string content, string file_name)
string preprocess_shared_unit(SharedUnit* su)
{
string pc = "#include \""+get_cwd()+"/src/lib/uce_gen.h\" \n";
string content = file_get_contents(su->file_name);
string pc = "#include \""+context->server_state->config.COMPILER_SYS_PATH +"/src/lib/uce_gen.h\" \n";
string token = "";
string html_buffer = "";
u8 mode = 0;
@ -117,11 +93,11 @@ string preprocess(string content, string file_name)
u32 len = token.length() + 3 + end_pos - i;
html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0)));
i += len - 1;
pc.append(process_html_literal(html_buffer, file_name));
pc.append(process_html_literal(su, html_buffer));
}
else
{
printf("(!) unterminated HTML literal <%s> in %s", token.c_str(), file_name.c_str());
printf("(!) unterminated HTML literal <%s> in %s", token.c_str(), su->file_name.c_str());
}
mode = 0;
}
@ -160,9 +136,39 @@ string preprocess(string content, string file_name)
return(pc);
}
void load_shared_unit(SharedUnit* su)
void setup_unit_paths(SharedUnit* su, string file_name)
{
su->file_name = file_name;
if(su->src_path.length() > 0) // we did this already
return;
su->src_path = dirname(file_name);
su->bin_path = context->server_state->config.BIN_DIRECTORY + su->src_path;
su->pre_path = context->server_state->config.BIN_DIRECTORY + su->src_path;
su->src_file_name = basename(file_name);
su->bin_file_name = su->src_file_name + ".so";
su->pre_file_name = su->src_file_name + ".cpp";
su->so_name = su->bin_path + "/" + su->bin_file_name;
}
void load_shared_unit(SharedUnit* su, string file_name)
{
setup_unit_paths(su, file_name);
su->on_render = 0;
su->on_setup = 0;
su->compiler_messages = "";
if(!file_exists(su->so_name))
{
printf("(i) unit file not found: %s\n", su->so_name.c_str());
su->compiler_messages = "unit file not found";
return;
}
su->so_handle = dlopen(su->so_name.c_str(), RTLD_NOW);
if(su->so_handle)
{
@ -181,79 +187,95 @@ void load_shared_unit(SharedUnit* su)
}
}
SharedUnit* compile_shared_unit(string file_name)
void compile_shared_unit(SharedUnit* su, string file_name)
{
SharedUnit* su = new SharedUnit();
setup_unit_paths(su, file_name);
string src_path = dirname(file_name);
string src_fn = basename(file_name);
string dest_path = Config.BIN_DIRECTORY + src_path;
string pp_fn = src_fn + ".cpp";
string so_fn = src_fn + ".so";
if(!file_exists(su->file_name))
{
su->compiler_messages = "source file not found";
return;
}
su->file_name = file_name;
su->so_name = dest_path + "/" + so_fn;
shell_exec("mkdir -p " + shell_escape(su->pre_path));
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(su));
string pc = preprocess(file_get_contents(file_name), file_name);
file_put_contents(dest_path + "/" + pp_fn, pc);
printf("Config.COMPILE_SCRIPT %s\n", string(su->pre_path + "/" + su->pre_file_name).c_str());
su->compiler_messages = trim(shell_exec(Config.COMPILE_SCRIPT+" "+
shell_escape(src_path)+" "+
shell_escape(dest_path)+" "+
shell_escape(src_fn)+" "+
shell_escape(pp_fn)+" "+
shell_escape(so_fn)
su->compiler_messages = trim(shell_exec(context->server_state->config.COMPILE_SCRIPT+" "+
shell_escape(su->src_path)+" "+
shell_escape(su->bin_path)+" "+
shell_escape(su->file_name)+" "+
shell_escape(su->pre_file_name)+" "+
shell_escape(su->bin_file_name)
));
if(su->compiler_messages.length() > 0)
{
printf("%s \n", su->compiler_messages.c_str());
printf("(i) compiled unit %s\n", file_name.c_str());
load_shared_unit(su);
return(su);
}
else
{
load_shared_unit(su, file_name);
printf("(i) compiled unit %s\n", file_name.c_str());
}
}
SharedUnit* get_shared_unit(string file_name)
{
SharedUnit* su = units[file_name];
if(su && su->last_compiled < file_mtime(file_name))
SharedUnit* su = context->server_state->units[file_name];
auto mod_time = file_mtime(file_name);
bool do_recompile = false;
if(su && (su->last_compiled < mod_time || mod_time == 0))
{
delete su;
su = 0;
do_recompile = true;
}
if(!su)
{
su = units[file_name] = compile_shared_unit(file_name);
su = new SharedUnit();
if(do_recompile)
{
compile_shared_unit(su, file_name);
}
else
{
load_shared_unit(su, file_name);
if(!su->so_handle)
compile_shared_unit(su, file_name);
}
context->server_state->units[file_name] = su;
}
return(su);
}
void invoke(Request* req, string file_name)
void invoke(string file_name)
{
printf("(i) invoke(%s)\n", file_name.c_str());
auto su = get_shared_unit(file_name);
if(!su)
{
printf("Error loading unit %s\n", su->file_name.c_str());
printf("Error loading unit %s\n", file_name.c_str());
context->print("Error loading unit: "+file_name);
}
else if(!su->on_render)
{
req->print("Compiler error: "+su->compiler_messages);
context->print("Compiler error: "+su->compiler_messages);
}
else
{
if(su->compiler_messages.length() > 0)
req->print(su->compiler_messages);
context->print(su->compiler_messages);
else
{
su->on_setup(req);
string prev_wd = get_cwd();
set_cwd(su->src_path);
su->on_setup(context);
su->on_render();
set_cwd(prev_wd);
}
}
}
void invoke(string file_name)
{
return(invoke(context, file_name));
}

View File

@ -1,4 +1,4 @@
struct Settings {
struct ServerSettings {
string BIN_DIRECTORY = "work";
string COMPILE_SCRIPT = "scripts/compile";
@ -6,6 +6,7 @@ struct Settings {
string CONTENT_TYPE = "text/html; charset=utf-8";
string SOCKET_PATH = "/run/uce.sock";
string TMP_UPLOAD = "/tmp";
string COMPILER_SYS_PATH = "";
u32 LISTEN_PORT = 9993;
} Config;
};

View File

@ -1,5 +1,6 @@
string shell_exec(string cmd)
{
printf("(i) shell_exec(%s)\n", cmd.c_str());
string data;
FILE * stream;
const int max_buffer = 256;
@ -98,6 +99,11 @@ string get_cwd()
return(std::filesystem::current_path());
}
void set_cwd(string path)
{
chdir(path.c_str());
}
time_t file_mtime(string file_name)
{
struct stat info;

View File

@ -10,6 +10,7 @@
#include <vector>
#include <sys/stat.h>
#include <ctime>
#include <dlfcn.h>
typedef std::string string;
@ -33,11 +34,47 @@ typedef long long s64;
typedef std::map<string, string> StringMap;
typedef std::vector<string> StringList;
typedef void (*invoke_handler)(string file_name);
struct UploadedFile {
string file_name;
string tmp_name;
u32 size;
};
struct Request;
typedef void (*call_handler)();
typedef void (*request_handler)(Request* request);
struct SharedUnit {
string file_name;
string so_name;
string src_path;
string bin_path;
string pre_path;
string src_file_name;
string bin_file_name;
string pre_file_name;
void* so_handle;
request_handler on_setup;
call_handler on_render;
string compiler_messages;
time_t last_compiled;
~SharedUnit()
{
if(so_handle)
{
dlclose(so_handle);
}
}
};
#include "dtree.h"

View File

@ -3,9 +3,17 @@
#include "datastructures.h"
#include "sys.h"
#include "time.h"
#include "uri.h"
struct FastCGIRequest {
struct ServerState {
std::map<string, SharedUnit*> units;
ServerSettings config;
} server_state;
struct Request {
ServerState* server_state;
StringMap params;
StringMap get;
@ -29,13 +37,15 @@ struct FastCGIRequest {
};
typedef FastCGIRequest Request;
typedef Request FastCGIRequest;
Request* context;
#include "uri.h"
#include "compiler.h"
extern "C" void set_current_request(Request* _request)
{
context = _request;
}
#include "compiler.h"

View File

@ -177,7 +177,7 @@ struct URI {
{
nibble("=\"", field);
UploadedFile f;
f.tmp_name = Config.TMP_UPLOAD + to_string(rand());
f.tmp_name = context->server_state->config.TMP_UPLOAD + to_string(rand());
f.file_name = nibble("\"", field);
string bin = field.substr(4, field.length()-6);
f.size = bin.length();

View File

@ -38,9 +38,11 @@ int handle_complete(FastCGIRequest& request) {
// The event handler can also be a class member function. This
// event occurs when the parameters and standard input streams are
// both closed, and thus the request is complete.
context = &request;
request.server_state = &server_state;
request.time_start = microtime();
request.header["Content-Type"] = Config.CONTENT_TYPE;
request.header["Content-Type"] = context->server_state->config.CONTENT_TYPE;
request.get = URI::parse_query(request.params["QUERY_STRING"]);
string ct_info = request.params["CONTENT_TYPE"];
@ -59,7 +61,7 @@ int handle_complete(FastCGIRequest& request) {
}
}
invoke(&request, request.params["SCRIPT_FILENAME"]);
invoke(request.params["SCRIPT_FILENAME"]);
string headers = var_dump(request.header, "", "\r\n") + "\r\n";
request.out = headers + request.out;
@ -87,11 +89,17 @@ int main(int argc, char** argv)
server.data_handler(&handle_data);
server.complete_handler(&handle_complete);
if(Config.LISTEN_PORT)
server.listen(Config.LISTEN_PORT);
if(Config.SOCKET_PATH != "")
server.listen(Config.SOCKET_PATH);
chmod(Config.SOCKET_PATH.c_str(), S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if(server_state.config.COMPILER_SYS_PATH == "")
server_state.config.COMPILER_SYS_PATH = get_cwd();
server_state.config.BIN_DIRECTORY =
server_state.config.COMPILER_SYS_PATH + "/" + server_state.config.BIN_DIRECTORY;
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);
//server.process(100);
//server.process();

View File

@ -4,7 +4,7 @@ RENDER()
{
<html>
<link rel="stylesheet" href='style.css?v=1'></link>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Index
@ -13,6 +13,7 @@ RENDER()
<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>
</ul>
<pre><?= var_dump(context->params) ?></pre>
</html>

View File

@ -65,7 +65,8 @@ textarea {
pre {
height: 20%;
overflow: auto;
padding. 8px;
padding: 8px;
border: 2px solid rgba(0,0,0,0.2);
background: rgba(100,100,100,0.15);
font-family: monospace;
}

View File

@ -0,0 +1,6 @@
RENDER()
{
echo("Sub-Invoke Working dir: " + get_cwd() + "\n");
}

19
test/working-dir.uce Normal file
View File

@ -0,0 +1,19 @@
RENDER()
{
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Working Directory
</h1>
<pre><?
echo("Base WD: " + get_cwd() + "\n");
invoke("/Code/uce.openfu.com/uce/test/test2/working-dir-test.uce");
?></pre>
<pre><?= var_dump(context->params) ?></pre>
</>
}

View File

@ -16,7 +16,6 @@ Bugs
=================================
- shell_escape()
- include path
- current request working directory
- preprocessor
- nested tags