diff --git a/modules/http_server_simple/http_parser.cpp b/modules/http_server_simple/http_parser.cpp index 8e327d1f64..3c1dc3523a 100644 --- a/modules/http_server_simple/http_parser.cpp +++ b/modules/http_server_simple/http_parser.cpp @@ -34,6 +34,8 @@ #include "./http_parser/http_parser.h" #include "./multipart_parser_c/multipart_parser.h" #include "core/log/logger.h" +#include "core/os/dir_access.h" +#include "core/os/os.h" #include "modules/web/http/web_server_request.h" @@ -97,7 +99,13 @@ int HTTPParser::read_from_buffer(const char *p_buffer, const int p_data_length) HTTPParser::HTTPParser() { // Should always get set from the outside, if it remains 0 it's a bug. max_request_size = 0; + request_max_file_upload_size = 0; + upload_file_store_type = WebServerSimple::FILE_UPLOAD_STORE_TYPE_MEMORY; + + _upload_file_access = NULL; + _current_request_size = 0; + _current_upload_files_size = 0; _is_ready = false; _content_type = REQUEST_CONTENT_URLENCODED; @@ -140,6 +148,20 @@ HTTPParser::~HTTPParser() { memdelete(parser); memdelete(settings); parser = nullptr; + + if (_upload_file_access) { + String path = _upload_file_access->get_path(); + _upload_file_access->close(); + memdelete(_upload_file_access); + _upload_file_access = NULL; + + DirAccess *d = DirAccess::create_for_path(path.get_base_dir()); + + if (d) { + d->remove(path); + memdelete(d); + } + } } void HTTPParser::_bind_methods() { @@ -169,6 +191,7 @@ void HTTPParser::_process_multipart_header_value(const String &val) { if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) { _multipart_form_name.remove(0); + //TODO check if this should be _multipart_form_name.remove(_multipart_form_name.length() - 1); _multipart_form_name.remove(_multipart_form_name.size() - 1); } } else if (kk == "filename") { @@ -178,8 +201,55 @@ void HTTPParser::_process_multipart_header_value(const String &val) { if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) { _multipart_form_name.remove(0); + //TODO check if this should be _multipart_form_name.remove(_multipart_form_name.length() - 1); _multipart_form_name.remove(_multipart_form_name.size() - 1); } + + if (upload_file_store_type == WebServerSimple::FILE_UPLOAD_STORE_TYPE_TEMP_FILES) { + if (_upload_file_access) { + ERR_PRINT("BUG! if (_upload_file_access) is true!"); + _upload_file_access->close(); + memdelete(_upload_file_access); + _upload_file_access = NULL; + } + + DirAccess *da = DirAccess::create_for_path(upload_temp_file_store_path); + + if (!da) { + // NO fallback! + ERR_PRINT("upload_file_store_type == FILE_UPLOAD_STORE_TYPE_TEMP_FILES, but temp file path cannot be opened! Sending Error!"); + _error = true; + return; + } + + // Just use OS::Time for now. These names are internal, and if the file is not copied out it will get deleted automatically. + // If filename exists just add values + String fbase_name = upload_temp_file_store_path + itos(OS::get_singleton()->get_unix_time()) + "_" + itos(OS::get_singleton()->get_ticks_usec()); + + String fname = fbase_name; + int fcounter = 0; + + while (da->file_exists(fname) && fcounter < 100) { + fname = fbase_name + "_" + itos(fcounter); + ++fcounter; + } + + memdelete(da); + + Error err; + _upload_file_access = FileAccess::open(fname, FileAccess::WRITE, &err); + + if (err != OK) { + ERR_PRINT(vformat("upload_file_store_type == FILE_UPLOAD_STORE_TYPE_TEMP_FILES, but temp file cannot be opened! Sending Error! Error: %d, FileName: %s", itos(err), fname)); + _error = true; + + if (_upload_file_access) { + memdelete(_upload_file_access); + } + } + + _upload_file_full_path = fname; + } } } @@ -576,12 +646,38 @@ int HTTPParser::on_multipart_part_data_cb(const char *at, size_t length) { ERR_PRINT("on_multipart_part_data_cb"); #endif - int l = static_cast(length); - int mfdofs = _multipart_form_data.size(); - _multipart_form_data.resize(mfdofs + length); - char *w = _multipart_form_data.ptrw(); - for (int i = 0; i < l; ++i) { - w[mfdofs++] = at[i]; + if (_upload_file_access) { + _upload_file_access->store_buffer((const uint8_t *)at, (uint64_t)length); + + _current_upload_files_size += length; + + if (_current_upload_files_size >= request_max_file_upload_size) { + _error = true; + +#if PROTOCOL_ERROR_LOGGING_ENABLED + PLOG_ERR("_current_upload_files_size >= request_max_file_upload_size"); +#endif + + _upload_file_access->close(); + memdelete(_upload_file_access); + _upload_file_access = NULL; + + DirAccess *d = DirAccess::create_for_path(_upload_file_full_path.get_base_dir()); + + if (d) { + d->remove(_upload_file_full_path); + memdelete(d); + } + } + + } else { + int l = static_cast(length); + int mfdofs = _multipart_form_data.size(); + _multipart_form_data.resize(mfdofs + length); + char *w = _multipart_form_data.ptrw(); + for (int i = 0; i < l; ++i) { + w[mfdofs++] = at[i]; + } } return 0; @@ -606,19 +702,27 @@ int HTTPParser::on_multipart_part_data_end_cb() { #endif if (_multipart_form_is_file) { - if (_multipart_form_data.size() > 0) { - PoolByteArray file_data; - int len = _multipart_form_data.size(); - file_data.resize(len); - PoolByteArray::Write w = file_data.write(); - const char *r = _multipart_form_data.ptr(); - for (int i = 0; i < len; i++) { - w[i] = r[i]; - } + if (_upload_file_access) { + _upload_file_access->close(); + memdelete(_upload_file_access); + _upload_file_access = NULL; + + _request->add_file_temp_file(_multipart_form_name, _multipart_form_filename, _upload_file_full_path); + } else { + if (_multipart_form_data.size() > 0) { + PoolByteArray file_data; + int len = _multipart_form_data.size(); + file_data.resize(len); + PoolByteArray::Write w = file_data.write(); + const char *r = _multipart_form_data.ptr(); + for (int i = 0; i < len; i++) { + w[i] = r[i]; + } - w.release(); + w.release(); - _request->add_file(_multipart_form_name, _multipart_form_filename, file_data); + _request->add_file_memory(_multipart_form_name, _multipart_form_filename, file_data); + } } } else { String s = String::utf8(_multipart_form_data.ptr(), _multipart_form_data.size()); diff --git a/modules/http_server_simple/http_parser.h b/modules/http_server_simple/http_parser.h index f5d0d7a890..415e7395d5 100644 --- a/modules/http_server_simple/http_parser.h +++ b/modules/http_server_simple/http_parser.h @@ -34,9 +34,12 @@ #include "core/containers/vector.h" #include "core/string/ustring.h" +#include "core/os/file_access.h" #include "core/object/reference.h" +#include "web_server_simple.h" + class SimpleWebServerRequest; struct http_parser; struct http_parser_settings; @@ -54,6 +57,10 @@ class HTTPParser : public Reference { }; uint64_t max_request_size; + uint64_t request_max_file_upload_size; + + WebServerSimple::FileUploadStoreType upload_file_store_type; + String upload_temp_file_store_path; Ref get_next_request(); int get_request_count() const; @@ -76,6 +83,10 @@ class HTTPParser : public Reference { String _partial_data; uint64_t _current_request_size; + uint64_t _current_upload_files_size; + + String _upload_file_full_path; + FileAccess *_upload_file_access; Ref _request; Vector> _requests; diff --git a/modules/http_server_simple/http_server_simple.cpp b/modules/http_server_simple/http_server_simple.cpp index 62e6fc62f2..1c763a60b3 100644 --- a/modules/http_server_simple/http_server_simple.cpp +++ b/modules/http_server_simple/http_server_simple.cpp @@ -586,7 +586,6 @@ HTTPServerConnection::HTTPServerConnection() { _timeout_usec = 20 * 1000 * 1000; _http_parser.instance(); - _http_parser->max_request_size = max_request_size; time = 0; memset(req_buf, 0, sizeof(req_buf)); @@ -681,8 +680,10 @@ void HTTPServerSimple::poll() { connection->_web_server = _web_server; connection->_http_server = this; - connection->max_request_size = max_request_size; connection->_http_parser->max_request_size = max_request_size; + connection->_http_parser->request_max_file_upload_size = request_max_file_upload_size; + connection->_http_parser->upload_file_store_type = upload_file_store_type; + connection->_http_parser->upload_temp_file_store_path = upload_temp_file_store_path; connection->use_ssl = use_ssl; connection->key = key; @@ -842,6 +843,9 @@ HTTPServerSimple::HTTPServerSimple() { server.instance(); stop(); + + max_request_size = 0; + request_max_file_upload_size = 0; } HTTPServerSimple::~HTTPServerSimple() { diff --git a/modules/http_server_simple/http_server_simple.h b/modules/http_server_simple/http_server_simple.h index a4a49c7439..dc6cbcba15 100644 --- a/modules/http_server_simple/http_server_simple.h +++ b/modules/http_server_simple/http_server_simple.h @@ -46,6 +46,8 @@ #include "modules/web/http/http_server_enums.h" +#include "web_server_simple.h" + class HTTPParser; class WebServerSimple; class WebServerRequest; @@ -78,8 +80,6 @@ class HTTPServerConnection : public Reference { WebServerSimple *_web_server; HTTPServerSimple *_http_server; - uint64_t max_request_size; - bool use_ssl = false; Ref key; Ref _certificate; @@ -126,6 +126,10 @@ class HTTPServerSimple : public Reference { WebServerSimple *_web_server; uint64_t max_request_size; + uint64_t request_max_file_upload_size; + + WebServerSimple::FileUploadStoreType upload_file_store_type; + String upload_temp_file_store_path; RBMap mimes; diff --git a/modules/http_server_simple/simple_web_server_request.cpp b/modules/http_server_simple/simple_web_server_request.cpp index e8814f2e8f..570f63d56f 100644 --- a/modules/http_server_simple/simple_web_server_request.cpp +++ b/modules/http_server_simple/simple_web_server_request.cpp @@ -43,6 +43,8 @@ #include "http_server_simple.h" #include "modules/web/http/web_permission.h" +#include "core/os/dir_access.h" + String SimpleWebServerRequest::get_cookie(const String &key) { for (int i = 0; i < _cookies.size(); ++i) { const CookieData &d = _cookies[i]; @@ -58,8 +60,6 @@ HTTPServerEnums::HTTPMethod SimpleWebServerRequest::get_method() const { return _method; } -void SimpleWebServerRequest::parse_files() { -} int SimpleWebServerRequest::get_file_count() const { return _files.size(); } @@ -73,26 +73,122 @@ String SimpleWebServerRequest::get_file_key(const int index) const { return _files[index].file_name; } -int SimpleWebServerRequest::get_file_length(const int index) const { +uint64_t SimpleWebServerRequest::get_file_length(const int index) const { ERR_FAIL_INDEX_V(index, _files.size(), 0); - return _files[index].data.size(); + const FileEntry &e = _files[index]; + + if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) { + return e.data.size(); + } + + Error err; + FileAccess *fa = FileAccess::open(e.path, FileAccess::READ, &err); + + ERR_FAIL_NULL_V(fa, 0); + + if (err != OK) { + memdelete(fa); + return 0; + } + + uint64_t len = fa->get_len(); + + memdelete(fa); + + return len; } PoolByteArray SimpleWebServerRequest::get_file_data(const int index) const { ERR_FAIL_INDEX_V(index, _files.size(), PoolByteArray()); - return _files[index].data; + const FileEntry &e = _files[index]; + + if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) { + return e.data; + } + + Error err; + FileAccess *f = FileAccess::open(e.path, FileAccess::READ, &err); + if (!f) { + ERR_FAIL_V_MSG(PoolByteArray(), "Can't open file from path '" + String(e.path) + "'."); + } + + PoolByteArray data; + data.resize(f->get_len()); + PoolByteArray::Write w = data.write(); + uint8_t *dptr = w.ptr(); + + f->get_buffer(dptr, data.size()); + memdelete(f); + + return data; } String SimpleWebServerRequest::get_file_data_str(const int index) const { ERR_FAIL_INDEX_V(index, _files.size(), ""); - PoolByteArray::Read r = _files[index].data.read(); + const FileEntry &e = _files[index]; + + if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) { + PoolByteArray::Read r = _files[index].data.read(); - String ret = reinterpret_cast(r.ptr()); + String ret = reinterpret_cast(r.ptr()); - r.release(); + r.release(); - return ret; + return ret; + } + + Error err; + String data = FileAccess::get_file_as_string(e.path, &err); + + ERR_FAIL_COND_V_MSG(err != OK, "", vformat("Error accessing file! Error: %d", err)); + + return data; +} +Error SimpleWebServerRequest::move_file(const int index, const String &p_dest_file) { + ERR_FAIL_INDEX_V(index, _files.size(), ERR_INVALID_PARAMETER); + + DirAccess *dir = DirAccess::create_for_path(p_dest_file.get_base_dir()); + + if (!dir) { + return ERR_FILE_BAD_PATH; + } + + if (dir->file_exists(p_dest_file)) { + return ERR_ALREADY_IN_USE; + } + + const FileEntry &e = _files[index]; + + if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) { + memdelete(dir); + + Error err; + FileAccess *f = FileAccess::open(e.path, FileAccess::WRITE, &err); + if (!f) { + return ERR_FILE_BAD_PATH; + } + + PoolByteArray::Read r = e.data.read(); + const uint8_t *rptr = r.ptr(); + + f->store_buffer(rptr, e.data.size()); + + return OK; + } + + dir->rename(e.path, p_dest_file); + memdelete(dir); + + e.moved = true; + e.path = p_dest_file; + + return OK; +} +bool SimpleWebServerRequest::is_file_moved(const int index) const { + ERR_FAIL_INDEX_V(index, _files.size(), true); + + return _files[index].moved; } String SimpleWebServerRequest::get_parameter(const String &key) const { @@ -271,8 +367,9 @@ void SimpleWebServerRequest::set_host(const String &value) { _host = value; } -void SimpleWebServerRequest::add_file(const String &key, const String &file_name, const PoolByteArray &data) { +void SimpleWebServerRequest::add_file_memory(const String &key, const String &file_name, const PoolByteArray &data) { FileEntry e; + e.type = FileEntry::FILE_ENTRY_TYPE_MEMORY; e.key = key; e.file_name = file_name; e.data = data; @@ -280,6 +377,16 @@ void SimpleWebServerRequest::add_file(const String &key, const String &file_name _files.push_back(e); } +void SimpleWebServerRequest::add_file_temp_file(const String &key, const String &file_name, const String &path) { + FileEntry e; + e.type = FileEntry::FILE_ENTRY_TYPE_TEMP_FILE; + e.key = key; + e.file_name = file_name; + e.path = path; + + _files.push_back(e); +} + void SimpleWebServerRequest::add_cookie_data(const String &key, const String &value) { CookieData d; d.key = key; @@ -303,6 +410,20 @@ SimpleWebServerRequest::SimpleWebServerRequest() { } SimpleWebServerRequest::~SimpleWebServerRequest() { + for (int i = 0; i < _files.size(); ++i) { + const FileEntry &e = _files[i]; + + if (e.type == FileEntry::FILE_ENTRY_TYPE_TEMP_FILE) { + if (!e.moved && !e.path.empty()) { + DirAccess *d = DirAccess::create_for_path(e.path.get_base_dir()); + + if (d) { + d->remove(e.path); + memdelete(d); + } + } + } + } } void SimpleWebServerRequest::_bind_methods() { diff --git a/modules/http_server_simple/simple_web_server_request.h b/modules/http_server_simple/simple_web_server_request.h index 519354908a..57198ab216 100644 --- a/modules/http_server_simple/simple_web_server_request.h +++ b/modules/http_server_simple/simple_web_server_request.h @@ -58,13 +58,14 @@ class SimpleWebServerRequest : public WebServerRequest { virtual HTTPServerEnums::HTTPMethod get_method() const; - virtual void parse_files(); virtual int get_file_count() const; virtual String get_file_file_name(const int index) const; virtual String get_file_key(const int index) const; - virtual int get_file_length(const int index) const; + virtual uint64_t get_file_length(const int index) const; virtual PoolByteArray get_file_data(const int index) const; virtual String get_file_data_str(const int index) const; + virtual Error move_file(const int index, const String &p_dest_file); + virtual bool is_file_moved(const int index) const; virtual String get_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const; @@ -93,7 +94,8 @@ class SimpleWebServerRequest : public WebServerRequest { void set_parser_path(const String &value); void set_host(const String &value); - void add_file(const String &key, const String &file_name, const PoolByteArray &data); + void add_file_memory(const String &key, const String &file_name, const PoolByteArray &data); + void add_file_temp_file(const String &key, const String &file_name, const String &path); void add_cookie_data(const String &key, const String &value); @@ -121,9 +123,22 @@ class SimpleWebServerRequest : public WebServerRequest { String _host; struct FileEntry { + enum FileEntryType { + FILE_ENTRY_TYPE_MEMORY = 0, + FILE_ENTRY_TYPE_TEMP_FILE = 0, + }; + + mutable bool moved; + + FileEntryType type; String file_name; PoolByteArray data; String key; //form name key + mutable String path; + + FileEntry() { + moved = false; + } }; Vector _files; diff --git a/modules/http_server_simple/web_server_simple.cpp b/modules/http_server_simple/web_server_simple.cpp index 8f62a0cd19..e9e14e7554 100644 --- a/modules/http_server_simple/web_server_simple.cpp +++ b/modules/http_server_simple/web_server_simple.cpp @@ -129,6 +129,37 @@ void WebServerSimple::set_max_request_size(const int val) { _apply_max_request_size_type(); } +WebServerSimple::FileUploadStoreType WebServerSimple::upload_get_file_store_type() { + return _upload_file_store_type; +} +void WebServerSimple::upload_set_file_store_type(const FileUploadStoreType val) { + _upload_file_store_type = val; + property_list_changed_notify(); +} + +String WebServerSimple::upload_get_temp_file_store_path() { + return _upload_temp_file_store_path; +} +void WebServerSimple::upload_set_temp_file_store_path(const String &val) { + _upload_temp_file_store_path = val; +} + +WebServerSimple::MaxRequestSizeTypes WebServerSimple::upload_get_request_max_file_size_type() { + return _upload_request_max_file_size_type; +} +void WebServerSimple::upload_set_request_max_file_size_type(const MaxRequestSizeTypes val) { + _upload_request_max_file_size_type = val; + _apply_request_max_file_upload_size_type(); +} + +int WebServerSimple::upload_get_request_max_file_size() { + return _upload_request_max_file_size; +} +void WebServerSimple::upload_set_request_max_file_size(const int val) { + _upload_request_max_file_size = val; + _apply_request_max_file_upload_size_type(); +} + void WebServerSimple::add_mime_type(const String &file_extension, const String &mime_type) { _server->mimes[file_extension] = mime_type; } @@ -145,6 +176,9 @@ void WebServerSimple::_start() { WebServer::_start(); + _server->upload_file_store_type = _upload_file_store_type; + _server->upload_temp_file_store_path = _upload_temp_file_store_path.path_ensure_end_slash(); + if (!OS::get_singleton()->can_use_threads()) { _server->_use_worker_threads = false; } else { @@ -231,6 +265,11 @@ WebServerSimple::WebServerSimple() { _max_request_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE; _max_request_size = 3; + _upload_file_store_type = FILE_UPLOAD_STORE_TYPE_MEMORY; + _upload_temp_file_store_path = "user://http_temp_files/"; + _upload_request_max_file_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE; + _upload_request_max_file_size = 10; + _bind_port = 8080; _bind_host = "0.0.0.0"; @@ -251,6 +290,7 @@ WebServerSimple::WebServerSimple() { _server->_web_server = this; _apply_max_request_size_type(); + _apply_request_max_file_upload_size_type(); } WebServerSimple::~WebServerSimple() { @@ -267,6 +307,22 @@ void WebServerSimple::_apply_max_request_size_type() { _server->max_request_size = (static_cast(1) << (10 * static_cast(_max_request_size_type))) * static_cast(_max_request_size); } +void WebServerSimple::_apply_request_max_file_upload_size_type() { + _server->request_max_file_upload_size = (static_cast(1) << (10 * static_cast(_upload_request_max_file_size_type))) * static_cast(_upload_request_max_file_size); +} + +void WebServerSimple::_validate_property(PropertyInfo &property) const { + if (_upload_file_store_type == FILE_UPLOAD_STORE_TYPE_MEMORY) { + if (property.name.begins_with("upload_")) { + if (property.name == "upload_file_store_type") { + return; + } + + property.usage = 0; + } + } +} + void WebServerSimple::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PROCESS: { @@ -331,6 +387,24 @@ void WebServerSimple::_bind_methods() { ClassDB::bind_method(D_METHOD("set_max_request_size", "val"), &WebServerSimple::set_max_request_size); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_request_size"), "set_max_request_size", "get_max_request_size"); + ADD_GROUP("Upload", "upload_"); + + ClassDB::bind_method(D_METHOD("upload_get_file_store_type"), &WebServerSimple::upload_get_file_store_type); + ClassDB::bind_method(D_METHOD("upload_set_file_store_type", "val"), &WebServerSimple::upload_set_file_store_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_file_store_type", PROPERTY_HINT_ENUM, "Memory,Temp Files"), "upload_set_file_store_type", "upload_get_file_store_type"); + + ClassDB::bind_method(D_METHOD("upload_get_temp_file_store_path"), &WebServerSimple::upload_get_temp_file_store_path); + ClassDB::bind_method(D_METHOD("upload_set_temp_file_store_path", "val"), &WebServerSimple::upload_set_temp_file_store_path); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "upload_temp_file_store_path"), "upload_set_temp_file_store_path", "upload_get_temp_file_store_path"); + + ClassDB::bind_method(D_METHOD("upload_get_request_max_file_size_type"), &WebServerSimple::upload_get_request_max_file_size_type); + ClassDB::bind_method(D_METHOD("upload_set_request_max_file_size_type", "val"), &WebServerSimple::upload_set_request_max_file_size_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_request_max_file_size_type", PROPERTY_HINT_ENUM, "B,KB,MB,GB"), "upload_set_request_max_file_size_type", "upload_get_request_max_file_size_type"); + + ClassDB::bind_method(D_METHOD("upload_get_request_max_file_size"), &WebServerSimple::upload_get_request_max_file_size); + ClassDB::bind_method(D_METHOD("upload_set_request_max_file_size", "val"), &WebServerSimple::upload_set_request_max_file_size); + ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_request_max_file_size"), "upload_set_request_max_file_size", "upload_get_request_max_file_size"); + ClassDB::bind_method(D_METHOD("add_mime_type", "file_extension", "mime_type"), &WebServerSimple::add_mime_type); ClassDB::bind_method(D_METHOD("remove_mime_type", "file_extension"), &WebServerSimple::remove_mime_type); @@ -340,6 +414,9 @@ void WebServerSimple::_bind_methods() { BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_KILO_BYTE); BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_MEGA_BYTE); BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_GIGA_BYTE); + + BIND_ENUM_CONSTANT(FILE_UPLOAD_STORE_TYPE_MEMORY); + BIND_ENUM_CONSTANT(FILE_UPLOAD_STORE_TYPE_TEMP_FILES); } void WebServerSimple::_server_thread_poll(void *data) { diff --git a/modules/http_server_simple/web_server_simple.h b/modules/http_server_simple/web_server_simple.h index ba852f4196..20ba85ee77 100644 --- a/modules/http_server_simple/web_server_simple.h +++ b/modules/http_server_simple/web_server_simple.h @@ -56,6 +56,12 @@ class WebServerSimple : public WebServer { MAX_REQUEST_SIZE_TYPE_GIGA_BYTE = 3, }; + enum FileUploadStoreType { + FILE_UPLOAD_STORE_TYPE_MEMORY = 0, + FILE_UPLOAD_STORE_TYPE_TEMP_FILES, + //FILE_UPLOAD_STORE_TYPE_TEMP_FILES_SORTED_FOLDERS -> Use a hash as file name, and sort them into folders like /ab/cd/abcd... TODO + }; + int get_bind_port(); void set_bind_port(const int val); @@ -86,15 +92,26 @@ class WebServerSimple : public WebServer { MaxRequestSizeTypes get_max_request_size_type(); void set_max_request_size_type(const MaxRequestSizeTypes val); - // Note, that the implementation is extremely simple for now. - // This includes the entire request header, including file uploads, - // as right now uploaded files are stored in memory, - // so this will not change until temp files are implemented. - // (A big file upload / request can eat all the ram in a server!) + // This includes the entire request header, + // including file uploads (only if they are stored in memory) because + // then a big file upload / request can eat all the ram in a server! // Also 0 means 0, not unlimited -> This should NOT change (Reason: line above). int get_max_request_size(); void set_max_request_size(const int val); + FileUploadStoreType upload_get_file_store_type(); + void upload_set_file_store_type(const FileUploadStoreType val); + + String upload_get_temp_file_store_path(); + void upload_set_temp_file_store_path(const String &val); + + // Total, not per file (less room for misconfigurations). Only relevant if FILE_UPLOAD_STORE_TYPE_TEMP_FILES. + MaxRequestSizeTypes upload_get_request_max_file_size_type(); + void upload_set_request_max_file_size_type(const MaxRequestSizeTypes val); + + int upload_get_request_max_file_size(); + void upload_set_request_max_file_size(const int val); + void add_mime_type(const String &file_extension, const String &mime_type); void remove_mime_type(const String &file_extension); @@ -110,7 +127,9 @@ class WebServerSimple : public WebServer { protected: void _apply_max_request_size_type(); + void _apply_request_max_file_upload_size_type(); + void _validate_property(PropertyInfo &property) const; void _notification(int p_what); static void _bind_methods(); @@ -120,7 +139,6 @@ class WebServerSimple : public WebServer { bool _start_on_ready; - //TODO add binds to set path bool _use_ssl; String _ssl_key; String _ssl_cert; @@ -134,6 +152,11 @@ class WebServerSimple : public WebServer { MaxRequestSizeTypes _max_request_size_type; int _max_request_size; + FileUploadStoreType _upload_file_store_type; + String _upload_temp_file_store_path; + MaxRequestSizeTypes _upload_request_max_file_size_type; + int _upload_request_max_file_size; + Ref _server; bool _server_quit; Mutex _server_lock; @@ -144,5 +167,6 @@ class WebServerSimple : public WebServer { }; VARIANT_ENUM_CAST(WebServerSimple::MaxRequestSizeTypes); +VARIANT_ENUM_CAST(WebServerSimple::FileUploadStoreType); #endif diff --git a/modules/web/editor/web_node_editor_web_server_request.cpp b/modules/web/editor/web_node_editor_web_server_request.cpp index ce7703cd97..2374739566 100644 --- a/modules/web/editor/web_node_editor_web_server_request.cpp +++ b/modules/web/editor/web_node_editor_web_server_request.cpp @@ -45,8 +45,6 @@ HTTPServerEnums::HTTPMethod WebNodeEditorWebServerRequest::get_method() const { return HTTPServerEnums::HTTP_METHOD_GET; } -void WebNodeEditorWebServerRequest::parse_files() { -} int WebNodeEditorWebServerRequest::get_file_count() const { return 0; } @@ -56,7 +54,7 @@ String WebNodeEditorWebServerRequest::get_file_file_name(const int index) const String WebNodeEditorWebServerRequest::get_file_key(const int index) const { return ""; } -int WebNodeEditorWebServerRequest::get_file_length(const int index) const { +uint64_t WebNodeEditorWebServerRequest::get_file_length(const int index) const { return 0; } PoolByteArray WebNodeEditorWebServerRequest::get_file_data(const int index) const { diff --git a/modules/web/editor/web_node_editor_web_server_request.h b/modules/web/editor/web_node_editor_web_server_request.h index 4730d28bd0..ef912fac87 100644 --- a/modules/web/editor/web_node_editor_web_server_request.h +++ b/modules/web/editor/web_node_editor_web_server_request.h @@ -61,11 +61,10 @@ class WebNodeEditorWebServerRequest : public WebServerRequest { HTTPServerEnums::HTTPMethod get_method() const; - void parse_files(); int get_file_count() const; String get_file_file_name(const int index) const; String get_file_key(const int index) const; - int get_file_length(const int index) const; + uint64_t get_file_length(const int index) const; PoolByteArray get_file_data(const int index) const; String get_file_data_str(const int index) const; diff --git a/modules/web/http/web_server_request.cpp b/modules/web/http/web_server_request.cpp index 4fe0de2ed8..abab76d363 100644 --- a/modules/web/http/web_server_request.cpp +++ b/modules/web/http/web_server_request.cpp @@ -246,8 +246,6 @@ HTTPServerEnums::HTTPMethod WebServerRequest::get_method() const { return HTTPServerEnums::HTTP_METHOD_GET; } -void WebServerRequest::parse_files() { -} int WebServerRequest::get_file_count() const { return 0; } @@ -257,7 +255,7 @@ String WebServerRequest::get_file_file_name(const int index) const { String WebServerRequest::get_file_key(const int index) const { return String(); } -int WebServerRequest::get_file_length(const int index) const { +uint64_t WebServerRequest::get_file_length(const int index) const { return 0; } PoolByteArray WebServerRequest::get_file_data(const int index) const { @@ -266,6 +264,12 @@ PoolByteArray WebServerRequest::get_file_data(const int index) const { String WebServerRequest::get_file_data_str(const int index) const { return String(); } +Error WebServerRequest::move_file(const int index, const String &p_dest_file) { + return ERR_PRINTER_ON_FIRE; +} +bool WebServerRequest::is_file_moved(const int index) const { + return true; +} String WebServerRequest::get_parameter(const String &key) const { return String(); @@ -646,13 +650,14 @@ void WebServerRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("get_method"), &WebServerRequest::get_method); - ClassDB::bind_method(D_METHOD("parse_files"), &WebServerRequest::parse_files); ClassDB::bind_method(D_METHOD("get_file_count"), &WebServerRequest::get_file_count); ClassDB::bind_method(D_METHOD("get_file_file_name", "index"), &WebServerRequest::get_file_file_name); ClassDB::bind_method(D_METHOD("get_file_key", "index"), &WebServerRequest::get_file_key); ClassDB::bind_method(D_METHOD("get_file_length", "index"), &WebServerRequest::get_file_length); ClassDB::bind_method(D_METHOD("get_file_data", "index"), &WebServerRequest::get_file_data); ClassDB::bind_method(D_METHOD("get_file_data_str", "index"), &WebServerRequest::get_file_data_str); + ClassDB::bind_method(D_METHOD("move_file", "index", "dest_file"), &WebServerRequest::move_file); + ClassDB::bind_method(D_METHOD("is_file_moved", "index"), &WebServerRequest::is_file_moved); ClassDB::bind_method(D_METHOD("get_parameter", "key"), &WebServerRequest::get_parameter); ClassDB::bind_method(D_METHOD("get_post_parameter", "key"), &WebServerRequest::get_post_parameter); diff --git a/modules/web/http/web_server_request.h b/modules/web/http/web_server_request.h index f30758b8a1..368d30359f 100644 --- a/modules/web/http/web_server_request.h +++ b/modules/web/http/web_server_request.h @@ -110,13 +110,14 @@ class WebServerRequest : public Reference { virtual HTTPServerEnums::HTTPMethod get_method() const; - virtual void parse_files(); virtual int get_file_count() const; virtual String get_file_file_name(const int index) const; virtual String get_file_key(const int index) const; - virtual int get_file_length(const int index) const; + virtual uint64_t get_file_length(const int index) const; virtual PoolByteArray get_file_data(const int index) const; virtual String get_file_data_str(const int index) const; + virtual Error move_file(const int index, const String &p_dest_file); + virtual bool is_file_moved(const int index) const; virtual String get_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const; diff --git a/modules/web/http/web_server_request_scriptable.cpp b/modules/web/http/web_server_request_scriptable.cpp index 3d73cf3a10..734190152b 100644 --- a/modules/web/http/web_server_request_scriptable.cpp +++ b/modules/web/http/web_server_request_scriptable.cpp @@ -44,9 +44,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::get_method() const { return static_cast(m); } -void WebServerRequestScriptable::parse_files() { - call("_parse_files"); -} int WebServerRequestScriptable::get_file_count() const { return const_cast(this)->call("_get_file_count"); } @@ -56,7 +53,7 @@ String WebServerRequestScriptable::get_file_file_name(const int index) const { String WebServerRequestScriptable::get_file_key(const int index) const { return const_cast(this)->call("_get_file_key", index); } -int WebServerRequestScriptable::get_file_length(const int index) const { +uint64_t WebServerRequestScriptable::get_file_length(const int index) const { return const_cast(this)->call("_get_file_length", index); } PoolByteArray WebServerRequestScriptable::get_file_data(const int index) const { @@ -65,6 +62,12 @@ PoolByteArray WebServerRequestScriptable::get_file_data(const int index) const { String WebServerRequestScriptable::get_file_data_str(const int index) const { return const_cast(this)->call("_get_file_data_str", index); } +Error WebServerRequestScriptable::move_file(const int index, const String &p_dest_file) { + return (Error)(int)call("_move_file", index, p_dest_file); +} +bool WebServerRequestScriptable::is_file_moved(const int index) const { + return const_cast(this)->call("_is_file_moved", index); +} String WebServerRequestScriptable::get_parameter(const String &key) const { return const_cast(this)->call("_get_parameter", key); @@ -155,8 +158,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::_get_method() const { return HTTPServerEnums::HTTP_METHOD_GET; } -void WebServerRequestScriptable::_parse_files() { -} int WebServerRequestScriptable::_get_file_count() const { return 0; } @@ -175,6 +176,12 @@ PoolByteArray WebServerRequestScriptable::_get_file_data(const int index) const String WebServerRequestScriptable::_get_file_data_str(const int index) const { return String(); } +Error WebServerRequestScriptable::_move_file(const int index, const String &p_dest_file) { + return ERR_PRINTER_ON_FIRE; +} +bool WebServerRequestScriptable::_is_file_moved(const int index) const { + return true; +} String WebServerRequestScriptable::_get_parameter(const String &key) const { return String(); @@ -295,13 +302,14 @@ void WebServerRequestScriptable::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::INT, "_get_method")); - BIND_VMETHOD(MethodInfo("_parse_files")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_file_count")); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_file_name", PropertyInfo(Variant::INT, "index"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_key", PropertyInfo(Variant::INT, "index"))); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_file_length", PropertyInfo(Variant::INT, "index"))); BIND_VMETHOD(MethodInfo(Variant::POOL_BYTE_ARRAY, "_get_file_data", PropertyInfo(Variant::INT, "index"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_data_str", PropertyInfo(Variant::INT, "index"))); + BIND_VMETHOD(MethodInfo(Variant::INT, "_move_file", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::STRING, "dest_file"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_file_moved", PropertyInfo(Variant::INT, "index"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_parameter", PropertyInfo(Variant::STRING, "key"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_post_parameter", PropertyInfo(Variant::STRING, "key"))); @@ -336,13 +344,14 @@ void WebServerRequestScriptable::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_method"), &WebServerRequestScriptable::_get_method); - ClassDB::bind_method(D_METHOD("_parse_files"), &WebServerRequestScriptable::_parse_files); ClassDB::bind_method(D_METHOD("_get_file_count"), &WebServerRequestScriptable::_get_file_count); ClassDB::bind_method(D_METHOD("_get_file_file_name", "index"), &WebServerRequestScriptable::_get_file_file_name); ClassDB::bind_method(D_METHOD("_get_file_key", "index"), &WebServerRequestScriptable::_get_file_key); ClassDB::bind_method(D_METHOD("_get_file_length", "index"), &WebServerRequestScriptable::_get_file_length); ClassDB::bind_method(D_METHOD("_get_file_data", "index"), &WebServerRequestScriptable::_get_file_data); ClassDB::bind_method(D_METHOD("_get_file_data_str", "index"), &WebServerRequestScriptable::_get_file_data_str); + ClassDB::bind_method(D_METHOD("_move_file", "index", "dest_file"), &WebServerRequestScriptable::_move_file); + ClassDB::bind_method(D_METHOD("_is_file_moved", "index"), &WebServerRequestScriptable::_is_file_moved); ClassDB::bind_method(D_METHOD("_get_parameter", "key"), &WebServerRequestScriptable::_get_parameter); ClassDB::bind_method(D_METHOD("_get_post_parameter", "key"), &WebServerRequestScriptable::_get_post_parameter); diff --git a/modules/web/http/web_server_request_scriptable.h b/modules/web/http/web_server_request_scriptable.h index d9f34d5391..d5667cbf58 100644 --- a/modules/web/http/web_server_request_scriptable.h +++ b/modules/web/http/web_server_request_scriptable.h @@ -57,13 +57,14 @@ class WebServerRequestScriptable : public WebServerRequest { virtual HTTPServerEnums::HTTPMethod get_method() const; - virtual void parse_files(); virtual int get_file_count() const; virtual String get_file_file_name(const int index) const; virtual String get_file_key(const int index) const; - virtual int get_file_length(const int index) const; + virtual uint64_t get_file_length(const int index) const; virtual PoolByteArray get_file_data(const int index) const; virtual String get_file_data_str(const int index) const; + virtual Error move_file(const int index, const String &p_dest_file); + virtual bool is_file_moved(const int index) const; virtual String get_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const; @@ -98,13 +99,14 @@ class WebServerRequestScriptable : public WebServerRequest { virtual HTTPServerEnums::HTTPMethod _get_method() const; - virtual void _parse_files(); virtual int _get_file_count() const; virtual String _get_file_file_name(const int index) const; virtual String _get_file_key(const int index) const; virtual int _get_file_length(const int index) const; virtual PoolByteArray _get_file_data(const int index) const; virtual String _get_file_data_str(const int index) const; + virtual Error _move_file(const int index, const String &p_dest_file); + virtual bool _is_file_moved(const int index) const; virtual String _get_parameter(const String &key) const; virtual String _get_post_parameter(const String &key) const;