POST
This commit is contained in:
@@ -97,7 +97,7 @@ protected:
|
||||
bool close_socket;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::string> Pairs;
|
||||
typedef StringMap Pairs;
|
||||
|
||||
std::vector<int> listen_sockets;
|
||||
std::vector<std::string> listen_unlink;
|
||||
|
||||
+22
-15
@@ -1,6 +1,6 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define RENDER() extern "C" void render()
|
||||
#define RENDER() extern "C" void render()
|
||||
|
||||
typedef void (*call_handler)();
|
||||
typedef void (*request_handler)(Request* request);
|
||||
@@ -30,12 +30,12 @@ string process_html_literal(string content, string file_name)
|
||||
string pc;
|
||||
string HT_START = "context->print(R\"(";
|
||||
string HT_END = ")\");";
|
||||
|
||||
|
||||
u8 mode = 0;
|
||||
bool inside_quote = false;
|
||||
string code_buffer = "";
|
||||
bool is_field = false;
|
||||
|
||||
|
||||
for(u32 i = 0; i < content.length(); i++)
|
||||
{
|
||||
char c = content[i];
|
||||
@@ -53,10 +53,10 @@ string process_html_literal(string content, string file_name)
|
||||
if(is_field)
|
||||
{
|
||||
pc.append(
|
||||
HT_END +
|
||||
HT_END +
|
||||
"echo(html_escape( " +
|
||||
code_buffer +
|
||||
" )); " +
|
||||
" )); " +
|
||||
HT_START
|
||||
);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ string process_html_literal(string content, string file_name)
|
||||
}
|
||||
else
|
||||
{
|
||||
code_buffer.append(1, c);
|
||||
code_buffer.append(1, c);
|
||||
}
|
||||
}
|
||||
else if(!inside_quote && c == '<' && content[i+1] == '?')
|
||||
@@ -85,11 +85,11 @@ string process_html_literal(string content, string file_name)
|
||||
}
|
||||
mode = 1;
|
||||
}
|
||||
else if(c == '\"')
|
||||
/*else if(c == '\"')
|
||||
{
|
||||
inside_quote = !inside_quote;
|
||||
pc.append(1, c);
|
||||
}
|
||||
}*/
|
||||
else
|
||||
{
|
||||
pc.append(1, c);
|
||||
@@ -115,7 +115,7 @@ string preprocess(string content, string file_name)
|
||||
if(end_pos != string::npos)
|
||||
{
|
||||
u32 len = token.length() + 3 + end_pos - i;
|
||||
html_buffer.append(content.substr(i, len));
|
||||
html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0)));
|
||||
i += len - 1;
|
||||
pc.append(process_html_literal(html_buffer, file_name));
|
||||
}
|
||||
@@ -128,17 +128,24 @@ string preprocess(string content, string file_name)
|
||||
else if(mode == 1)
|
||||
{
|
||||
if(isspace(c) || c == '>')
|
||||
{
|
||||
mode = 2;
|
||||
if(token.length() > 0)
|
||||
html_buffer.append(1, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
token.append(1, c);
|
||||
html_buffer.append(1, c);
|
||||
html_buffer.append(1, c);
|
||||
}
|
||||
}
|
||||
else if(!inside_quote && c == '<' && isalpha(content[i+1]))
|
||||
else if(!inside_quote && c == '<' && (content[i+1] == '>' || isalpha(content[i+1])))
|
||||
{
|
||||
mode = 1;
|
||||
token = "";
|
||||
html_buffer = "";
|
||||
html_buffer.append(1, c);
|
||||
if(content[i+1] != '>')
|
||||
html_buffer.append(1, c);
|
||||
}
|
||||
else if(c == '\"')
|
||||
{
|
||||
@@ -203,7 +210,7 @@ SharedUnit* compile_shared_unit(string file_name)
|
||||
|
||||
printf("(i) compiled unit %s\n", file_name.c_str());
|
||||
|
||||
load_shared_unit(su);
|
||||
load_shared_unit(su);
|
||||
|
||||
return(su);
|
||||
}
|
||||
@@ -241,7 +248,7 @@ void invoke(Request* req, string file_name)
|
||||
else
|
||||
{
|
||||
su->on_setup(req);
|
||||
su->on_render();
|
||||
su->on_render();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,4 +256,4 @@ void invoke(Request* req, string file_name)
|
||||
void invoke(string file_name)
|
||||
{
|
||||
return(invoke(context, file_name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ string implode(StringList l, string delim = "\n")
|
||||
string html_escape(string s)
|
||||
{
|
||||
string result;
|
||||
|
||||
|
||||
for(u32 i = 0; i < s.length(); i++)
|
||||
{
|
||||
char c = s[i];
|
||||
@@ -111,4 +111,21 @@ string html_escape(f64 a)
|
||||
u64 int_val(string s, u32 base = 10)
|
||||
{
|
||||
return(strtoll(s.c_str(), 0, base));
|
||||
}
|
||||
}
|
||||
|
||||
string nibble(string div, string& haystack)
|
||||
{
|
||||
auto pos = haystack.find(div);
|
||||
if(pos == string::npos)
|
||||
{
|
||||
auto result = haystack;
|
||||
haystack.clear();
|
||||
return(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = haystack.substr(0, pos);
|
||||
haystack.erase(0, pos+div.length());
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ struct Settings {
|
||||
string LIT_ESC = "3d5b5_1";
|
||||
string CONTENT_TYPE = "text/html; charset=utf-8";
|
||||
string SOCKET_PATH = "/run/uce.sock";
|
||||
string TMP_UPLOAD = "/tmp";
|
||||
u32 LISTEN_PORT = 9993;
|
||||
|
||||
} Config;
|
||||
} Config;
|
||||
|
||||
@@ -110,3 +110,8 @@ time_t file_mtime(string file_name)
|
||||
return(info.st_mtime);
|
||||
}
|
||||
}
|
||||
|
||||
void unlink(string file_name)
|
||||
{
|
||||
remove(file_name.c_str());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
//#include <unordered_map>
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
#include <ctype.h>
|
||||
@@ -32,5 +33,11 @@ typedef long long s64;
|
||||
typedef std::map<string, string> StringMap;
|
||||
typedef std::vector<string> StringList;
|
||||
|
||||
struct UploadedFile {
|
||||
string file_name;
|
||||
string tmp_name;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
#include "dtree.h"
|
||||
|
||||
|
||||
+7
-3
@@ -6,14 +6,18 @@
|
||||
#include "uri.h"
|
||||
|
||||
struct FastCGIRequest {
|
||||
|
||||
StringMap params;
|
||||
StringMap get;
|
||||
StringMap post;
|
||||
std::vector<UploadedFile> uploaded_files;
|
||||
|
||||
StringMap header;
|
||||
URI uri;
|
||||
|
||||
|
||||
std::string in;
|
||||
std::string out;
|
||||
std::string err;
|
||||
|
||||
|
||||
f64 time_init;
|
||||
f64 time_start;
|
||||
f64 time_end;
|
||||
|
||||
@@ -137,6 +137,7 @@ struct URI {
|
||||
result[URI::decode(key)] = URI::decode(value);
|
||||
key = "";
|
||||
value = "";
|
||||
is_key = true;
|
||||
}
|
||||
else if(is_key)
|
||||
{
|
||||
@@ -153,6 +154,48 @@ struct URI {
|
||||
return(result);
|
||||
}
|
||||
|
||||
static StringMap parse_multipart(string q, string boundary, std::vector<UploadedFile>& uploaded_files)
|
||||
{
|
||||
StringMap result;
|
||||
|
||||
auto i = boundary.length();
|
||||
while(i < q.length())
|
||||
{
|
||||
auto end_pos = q.find(boundary, i);
|
||||
if(end_pos != string::npos)
|
||||
{
|
||||
string field = q.substr(i, end_pos - i);
|
||||
nibble(":", field);
|
||||
string ftype = trim(nibble(";", field));
|
||||
if(ftype == "form-data")
|
||||
{
|
||||
nibble("=\"", field);
|
||||
string field_name = nibble("\"", field);
|
||||
result[field_name] = field.substr(4, field.length()-6);
|
||||
}
|
||||
else if(ftype == "attachment")
|
||||
{
|
||||
nibble("=\"", field);
|
||||
UploadedFile f;
|
||||
f.tmp_name = Config.TMP_UPLOAD + to_string(rand());
|
||||
f.file_name = nibble("\"", field);
|
||||
string bin = field.substr(4, field.length()-6);
|
||||
f.size = bin.length();
|
||||
file_put_contents(f.tmp_name, bin);
|
||||
uploaded_files.push_back(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're done
|
||||
end_pos = q.length();
|
||||
}
|
||||
i = end_pos + boundary.length();
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static string decode(string q)
|
||||
{
|
||||
string result;
|
||||
|
||||
+26
-10
@@ -11,9 +11,6 @@ int handle_request(FastCGIRequest& request) {
|
||||
// server receives all parameters. There may be more data coming on the
|
||||
// standard input stream.
|
||||
request.time_init = microtime();
|
||||
request.out.reserve(128 * 1024);
|
||||
request.in.reserve(128 * 1024);
|
||||
request.err.reserve(128 * 1024);
|
||||
if (request.params.count("REQUEST_URI"))
|
||||
return 0; // OK, continue processing
|
||||
else
|
||||
@@ -42,20 +39,39 @@ int handle_complete(FastCGIRequest& request) {
|
||||
// event occurs when the parameters and standard input streams are
|
||||
// both closed, and thus the request is complete.
|
||||
request.time_start = microtime();
|
||||
|
||||
request.header["Content-Type"] = Config.CONTENT_TYPE;
|
||||
request.uri = URI::parse(request.params["REQUEST_URI"]);
|
||||
request.uri.parts["scheme"] = request.params["REQUEST_SCHEME"];
|
||||
request.uri.parts["method"] = request.params["REQUEST_METHOD"];
|
||||
request.uri.parts["host"] = request.params["HTTP_HOST"];
|
||||
request.get = URI::parse_query(request.params["QUERY_STRING"]);
|
||||
|
||||
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 = URI::parse_multipart(request.in, string("--")+ct_info, request.uploaded_files);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.post = URI::parse_query(request.in);
|
||||
}
|
||||
}
|
||||
|
||||
invoke(&request, request.params["SCRIPT_FILENAME"]);
|
||||
|
||||
string headers = var_dump(request.header, "", "\r\n") + "\r\n";
|
||||
request.out = headers + request.out;
|
||||
|
||||
|
||||
for( auto &f : request.uploaded_files)
|
||||
{
|
||||
unlink(f.tmp_name);
|
||||
}
|
||||
|
||||
request.time_end = microtime();
|
||||
printf("(r) %s\t%0.6fs\t%0.1fkB\n",
|
||||
request.params["REQUEST_URI"].c_str(),
|
||||
printf("(r) %s\t%0.6fs\t%0.1fkB\n",
|
||||
request.params["REQUEST_URI"].c_str(),
|
||||
request.time_end - request.time_start,
|
||||
(f32)(request.out.length()/1024)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user