Initial cleanup of the folder serve nodes, also added them and HTMLBuilder to the build.

This commit is contained in:
Relintai 2022-07-02 16:40:08 +02:00
parent 56d2ccbb26
commit f81018f712
9 changed files with 160 additions and 95 deletions

View File

@ -22,8 +22,8 @@ sources = [
"http/web_server_middleware.cpp",
"http/web_server_request.cpp",
"html/html_builder_bind.cpp",
"html/html_builder.cpp",
"http_server_simple/http_server_simple.cpp",
"http_server_simple/web_server_simple.cpp",
@ -35,6 +35,9 @@ sources = [
"nodes/static_pages/static_page.cpp",
"nodes/static_pages/static_page_file.cpp",
"nodes/static_pages/static_page_folder_files.cpp",
"nodes/folder_serve_nodes/browsable_folder_serve_node.cpp",
"nodes/folder_serve_nodes/folder_serve_node.cpp",
]
if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes':

View File

@ -38,6 +38,9 @@ def get_doc_classes():
"StaticPage",
"StaticPageFile",
"StaticPageFolderFiles",
"FolderServeNode",
"BrowsableFolderServeNode",
]

View File

@ -1,7 +1,4 @@
#include "html_builder.h"
#include "core/string.h"
#include "web/http/request.h"
HTMLTag *HTMLTag::str(const String &str) {
result += " " + str;
@ -826,10 +823,11 @@ HTMLTag *HTMLTag::reset() {
}
HTMLTag *HTMLTag::close() {
if (simple)
if (simple) {
result += "/>";
else
} else {
result += ">";
}
return this;
}
@ -2575,12 +2573,14 @@ HTMLBuilder *HTMLBuilder::form_post(const String &action, const String &cls, con
return this;
}
/*
HTMLBuilder *HTMLBuilder::form_post(const String &action, Request *request, const String &cls, const String &id) {
form_post(action, cls, id);
csrf_token(request);
return this;
}
*/
HTMLTag *HTMLBuilder::input_button() {
write_tag();
@ -3326,9 +3326,11 @@ HTMLBuilder *HTMLBuilder::csrf_token(const String &token) {
return this;
}
/*
HTMLBuilder *HTMLBuilder::csrf_token(Request *request) {
return csrf_token(request->get_csrf_token());
}
*/
void HTMLBuilder::f() {
write_tag();
@ -3359,7 +3361,8 @@ HTMLBuilder *HTMLBuilder::wns(const double val) {
HTMLBuilder *HTMLBuilder::wr(const double val, const bool p_trailing) {
write_tag();
result += String::num_real(val, p_trailing);
//TODO
//result += String::num_real(val, p_trailing);
return this;
}
@ -3393,13 +3396,10 @@ HTMLBuilder *HTMLBuilder::wbs(const bool val) {
return this;
}
// TODO!
HTMLBuilder *HTMLBuilder::we(const String &val) {
printf("HTMLBuilder::write_excaped NYI!");
write_tag();
result += val;
result += val.http_escape();
return this;
}
@ -3419,4 +3419,4 @@ HTMLBuilder::HTMLBuilder() {
}
HTMLBuilder::~HTMLBuilder() {
}
}

View File

@ -1,7 +1,7 @@
#ifndef HTML_BUILDER_H
#define HTML_BUILDER_H
#include "core/string.h"
#include "core/ustring.h"
class Request;
class HTMLBuilder;
@ -470,7 +470,7 @@ public:
HTMLBuilder *form_get(const String &action, const String &cls = "", const String &id = "");
HTMLBuilder *form_post(const String &action, const String &cls = "", const String &id = "");
// will add a csrf token from request
HTMLBuilder *form_post(const String &action, Request *request, const String &cls = "", const String &id = "");
//HTMLBuilder *form_post(const String &action, Request *request, const String &cls = "", const String &id = "");
HTMLTag *input_button();
HTMLTag *input_checkbox();
@ -521,7 +521,7 @@ public:
HTMLBuilder *input_hidden(const String &name, const String &value);
HTMLBuilder *csrf_token(const String &token);
HTMLBuilder *csrf_token(Request *request);
//HTMLBuilder *csrf_token(Request *request);
void f();
@ -548,4 +548,4 @@ protected:
HTMLTag tag;
};
#endif
#endif

View File

@ -1,21 +1,33 @@
#include "browsable_folder_serve_node.h"
#include "core/os/directory.h"
#include "web/file_cache.h"
#include "web/html/html_builder.h"
#include "web/http/request.h"
#include "core/os/dir_access.h"
void BrowsableFolderServeNode::_handle_request_main(Request *request) {
#include "../../html/html_builder.h"
#include "../../file_cache.h"
#include "../../http/web_permission.h"
#include "../../http/web_server_request.h"
#include "../../http/http_server_enums.h"
bool BrowsableFolderServeNode::get_should_render_menu() {
return _should_render_menu;
}
void BrowsableFolderServeNode::set_should_render_menu(const bool &val) {
_should_render_menu = val;
}
void BrowsableFolderServeNode::_handle_request_main(Ref<WebServerRequest> request) {
String file_name = request->get_path(true, false);
String *s = _folder_indexes[file_name];
if (!s) {
request->send_error(HTTP_STATUS_CODE_404_NOT_FOUND);
request->send_error(HTTPServerEnums::HTTP_STATUS_CODE_404_NOT_FOUND);
return;
}
if (should_render_menu) {
if (_should_render_menu) {
render_menu(request);
}
@ -23,7 +35,7 @@ void BrowsableFolderServeNode::_handle_request_main(Request *request) {
request->compile_and_send_body();
}
void BrowsableFolderServeNode::render_index(Request *request) {
void BrowsableFolderServeNode::render_index(Ref<WebServerRequest> request) {
String *s = _folder_indexes["/"];
if (!s) {
@ -32,29 +44,28 @@ void BrowsableFolderServeNode::render_index(Request *request) {
request->body += (*s);
}
void BrowsableFolderServeNode::render_preview(Request *request) {
void BrowsableFolderServeNode::render_preview(Ref<WebServerRequest> request) {
}
void BrowsableFolderServeNode::load() {
if (serve_folder == "") {
if (_serve_folder == "") {
return;
}
FolderServeNode::load();
evaluate_dir(serve_folder, true);
evaluate_dir(_serve_folder, true);
}
void BrowsableFolderServeNode::evaluate_dir(const String &path, const bool top_level) {
Ref<Directory> dir;
dir.instance();
DirAccess *dir = DirAccess::open(path);
ERR_FAIL_COND_MSG(dir->open_dir(path) != OK, "Error opening folde!r: " + String(path));
ERR_FAIL_COND_MSG(!dir, "Error opening folde!r: " + String(path));
String dir_uri;
if (!top_level) {
dir_uri = path.substr(serve_folder.size(), path.size() - serve_folder.size());
dir_uri = path.substr(_serve_folder.size(), path.size() - _serve_folder.size());
} else {
dir_uri = "/";
}
@ -62,23 +73,34 @@ void BrowsableFolderServeNode::evaluate_dir(const String &path, const bool top_l
Vector<String> folders;
Vector<String> files;
while (dir->next()) {
String np = dir->current_get_path();
np = np.substr(serve_folder.size(), np.size() - serve_folder.size());
dir->list_dir_begin();
if (dir->current_is_file()) {
files.push_back(np);
String file = dir->get_next();
while (file != "") {
String np = path.append_path(file);
String nnp = np.substr(_serve_folder.size(), np.size() - _serve_folder.size());
if (dir->current_is_dir() && file != "." && file != "..") {
folders.push_back(nnp);
evaluate_dir(np);
} else {
folders.push_back(np);
evaluate_dir(dir->current_get_path());
files.push_back(nnp);
}
file = dir->get_next();
}
dir->close_dir();
dir->list_dir_end();
folders.sort_inc();
files.sort_inc();
memdelete(dir);
folders.sort();
files.sort();
//folders.sort_inc();
//files.sort_inc();
render_dir_page(dir_uri, folders, files, top_level);
}
@ -101,7 +123,7 @@ void BrowsableFolderServeNode::render_dir_page(const String &dir_uri, const Vect
for (int i = 0; i < folders.size(); ++i) {
b.div("file_list_entry");
{
b.a(uri + folders[i])->w("(Folder) ")->w(folders[i].path_get_basename())->ca();
b.a(uri + folders[i])->w("(Folder) ")->w(folders[i].get_basename())->ca();
}
b.cdiv();
}
@ -109,29 +131,32 @@ void BrowsableFolderServeNode::render_dir_page(const String &dir_uri, const Vect
for (int i = 0; i < files.size(); ++i) {
b.div("file_list_entry");
{
b.a(uri + files[i])->w("(File) ")->w(files[i].path_get_basename())->ca();
b.a(uri + files[i])->w("(File) ")->w(files[i].get_basename())->ca();
}
b.cdiv();
}
}
b.cdiv();
String *s = new String();
s->append_str(b.result);
String *s = memnew(String);
s->operator+=(b.result);
_folder_indexes[dir_uri] = s;
}
BrowsableFolderServeNode::BrowsableFolderServeNode() :
FolderServeNode() {
should_render_menu = true;
BrowsableFolderServeNode::BrowsableFolderServeNode() {
_should_render_menu = true;
}
BrowsableFolderServeNode::~BrowsableFolderServeNode() {
for (std::map<String, String *>::iterator E = _folder_indexes.begin(); E != _folder_indexes.end(); E++) {
if (E->second) {
delete E->second;
const String *key = nullptr;
while ((key = _folder_indexes.next(key))) {
String k = *key;
String *v = _folder_indexes[k];
if (v) {
memdelete(v);
}
}

View File

@ -1,12 +1,14 @@
#ifndef BROWSABLE_FOLDER_SERVE_NODE_H
#define BROWSABLE_FOLDER_SERVE_NODE_H
#include "core/string.h"
#include <map>
#include "core/hash_map.h"
#include "core/ustring.h"
#include "folder_serve_node.h"
// On top of serving the files from the folder set to it's serve_folder property,
class WebServerRequest;
// On top of serving the files from the folder set to it's serve_folder property,
// this class also generates HTML directory lists. (Similar to apache's directory listing)
// It caches folder contents on ENTER_TREE, it does not watch for folder changes yet.
@ -19,26 +21,28 @@
// </div>
class BrowsableFolderServeNode : public FolderServeNode {
RCPP_OBJECT(BrowsableFolderServeNode, FolderServeNode);
GDCLASS(BrowsableFolderServeNode, FolderServeNode);
public:
void _handle_request_main(Request *request);
bool get_should_render_menu();
void set_should_render_menu(const bool &val);
void render_index(Request *request);
void render_preview(Request *request);
void _handle_request_main(Ref<WebServerRequest> request);
virtual void load();
void render_index(Ref<WebServerRequest> request);
void render_preview(Ref<WebServerRequest> request);
void load();
void evaluate_dir(const String &path, const bool top_level = false);
virtual void render_dir_page(const String &dir_uri, const Vector<String> &folders, const Vector<String> &files, const bool top_level);
bool should_render_menu;
BrowsableFolderServeNode();
~BrowsableFolderServeNode();
protected:
std::map<String, String *> _folder_indexes;
bool _should_render_menu;
HashMap<String, String *> _folder_indexes;
};
#endif
#endif

View File

@ -1,9 +1,17 @@
#include "folder_serve_node.h"
#include "web/http/request.h"
#include "web/http/web_permission.h"
#include "../../file_cache.h"
#include "../../http/web_permission.h"
#include "../../http/web_server_request.h"
void FolderServeNode::handle_request_main(Request *request) {
String FolderServeNode::get_serve_folder() {
return _serve_folder;
}
void FolderServeNode::set_serve_folder(const String &val) {
_serve_folder = val;
}
void FolderServeNode::_handle_request_main(Ref<WebServerRequest> request) {
if (_web_permission.is_valid()) {
if (_web_permission->activate(request)) {
return;
@ -20,12 +28,16 @@ void FolderServeNode::handle_request_main(Request *request) {
}
String file_name = request->get_path(true, false);
file_name = file_name.to_lower();
if (file_cache->wwwroot_has_file(file_name)) {
String fp = file_cache->wwwroot;
fp.append_path(file_name);
int file_indx = _file_cache->wwwroot_get_file_index(file_name);
if (file_indx != -1) {
String fp = _file_cache->get_wwwroot_abs();
fp = fp.append_path(file_name);
request->send_file(_file_cache->wwwroot_get_file_orig_path(file_indx));
request->send_file(fp);
return;
}
@ -35,16 +47,15 @@ void FolderServeNode::handle_request_main(Request *request) {
}
void FolderServeNode::load() {
file_cache->clear();
_file_cache->clear();
if (serve_folder == "") {
return;
if (_serve_folder == "") {
_file_cache->set_wwwroot(_serve_folder);
_file_cache->clear();
} else {
_file_cache->set_wwwroot(_serve_folder);
_file_cache->wwwroot_refresh_cache();
}
serve_folder.path_clean_end_slash();
file_cache->wwwroot = serve_folder;
file_cache->wwwroot_refresh_cache();
}
void FolderServeNode::_notification(const int what) {
@ -57,11 +68,17 @@ void FolderServeNode::_notification(const int what) {
}
}
FolderServeNode::FolderServeNode() :
WebNode() {
file_cache = new FileCache();
FolderServeNode::FolderServeNode() {
_file_cache.instance();
}
FolderServeNode::~FolderServeNode() {
}
void FolderServeNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_serve_folder"), &FolderServeNode::get_serve_folder);
ClassDB::bind_method(D_METHOD("set_serve_folder", "val"), &FolderServeNode::set_serve_folder);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "serve_folder"), "set_serve_folder", "get_serve_folder");
ClassDB::bind_method(D_METHOD("load"), &FolderServeNode::load);
}

View File

@ -1,33 +1,40 @@
#ifndef FOLDER_SERVE_NODE_H
#define FOLDER_SERVE_NODE_H
#include "core/string.h"
#include "core/reference.h"
#include "core/ustring.h"
#include "web/file_cache.h"
#include "web/http/web_node.h"
#include "../../http/web_node.h"
class WebServerRequest;
class FileCache;
// This class will serve the files from the folder set to it's serve_folder property.
// It will cache the folder's contents on ENTER_TREE, and will match against the cached list,
// this means directory walking (for example sending http://webapp.com/files/../../../etc/passwd),
// this means directory walking (for example sending http://webapp.com/files/../../../etc/passwd),
// and other techniques like it should not be possible.
class FolderServeNode : public WebNode {
RCPP_OBJECT(FolderServeNode, WebNode);
GDCLASS(FolderServeNode, WebNode);
public:
void handle_request_main(Request *request);
String get_serve_folder();
void set_serve_folder(const String &val);
void _handle_request_main(Ref<WebServerRequest> request);
virtual void load();
void _notification(const int what);
String serve_folder;
FolderServeNode();
~FolderServeNode();
protected:
FileCache *file_cache;
void _notification(const int what);
static void _bind_methods();
String _serve_folder;
Ref<FileCache> _file_cache;
};
#endif
#endif

View File

@ -46,6 +46,9 @@ SOFTWARE.
#include "nodes/static_pages/static_page_file.h"
#include "nodes/static_pages/static_page_folder_files.h"
#include "nodes/folder_serve_nodes/browsable_folder_serve_node.h"
#include "nodes/folder_serve_nodes/folder_serve_node.h"
void register_web_types() {
ClassDB::register_class<_HTMLBuilder>();
ClassDB::register_class<_HTMLTag>();
@ -71,6 +74,9 @@ void register_web_types() {
ClassDB::register_class<StaticPage>();
ClassDB::register_class<StaticPageFile>();
ClassDB::register_class<StaticPageFolderFiles>();
ClassDB::register_class<FolderServeNode>();
ClassDB::register_class<BrowsableFolderServeNode>();
}
void unregister_web_types() {