- Now WebServerSimple can also use temporary files for uploads.

- Added move_file() and is_file_moved()  helper methods to WebServerRequest.
- get_file_length() in WebServerRequest now returns uint64_t.
- Removed parse_files() from WebServerRequest. It's doesn't work well with how the http protocol works.
This commit is contained in:
Relintai 2024-03-09 23:39:33 +01:00
parent 432478cb70
commit f86c6440fb
14 changed files with 437 additions and 63 deletions

View File

@ -34,6 +34,8 @@
#include "./http_parser/http_parser.h" #include "./http_parser/http_parser.h"
#include "./multipart_parser_c/multipart_parser.h" #include "./multipart_parser_c/multipart_parser.h"
#include "core/log/logger.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" #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() { HTTPParser::HTTPParser() {
// Should always get set from the outside, if it remains 0 it's a bug. // Should always get set from the outside, if it remains 0 it's a bug.
max_request_size = 0; 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_request_size = 0;
_current_upload_files_size = 0;
_is_ready = false; _is_ready = false;
_content_type = REQUEST_CONTENT_URLENCODED; _content_type = REQUEST_CONTENT_URLENCODED;
@ -140,6 +148,20 @@ HTTPParser::~HTTPParser() {
memdelete(parser); memdelete(parser);
memdelete(settings); memdelete(settings);
parser = nullptr; 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() { 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("\"")) { if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) {
_multipart_form_name.remove(0); _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); _multipart_form_name.remove(_multipart_form_name.size() - 1);
} }
} else if (kk == "filename") { } 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("\"")) { if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) {
_multipart_form_name.remove(0); _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); _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,6 +646,31 @@ int HTTPParser::on_multipart_part_data_cb(const char *at, size_t length) {
ERR_PRINT("on_multipart_part_data_cb"); ERR_PRINT("on_multipart_part_data_cb");
#endif #endif
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<int>(length); int l = static_cast<int>(length);
int mfdofs = _multipart_form_data.size(); int mfdofs = _multipart_form_data.size();
_multipart_form_data.resize(mfdofs + length); _multipart_form_data.resize(mfdofs + length);
@ -583,6 +678,7 @@ int HTTPParser::on_multipart_part_data_cb(const char *at, size_t length) {
for (int i = 0; i < l; ++i) { for (int i = 0; i < l; ++i) {
w[mfdofs++] = at[i]; w[mfdofs++] = at[i];
} }
}
return 0; return 0;
} }
@ -606,6 +702,13 @@ int HTTPParser::on_multipart_part_data_end_cb() {
#endif #endif
if (_multipart_form_is_file) { if (_multipart_form_is_file) {
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) { if (_multipart_form_data.size() > 0) {
PoolByteArray file_data; PoolByteArray file_data;
int len = _multipart_form_data.size(); int len = _multipart_form_data.size();
@ -618,7 +721,8 @@ int HTTPParser::on_multipart_part_data_end_cb() {
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 { } else {
String s = String::utf8(_multipart_form_data.ptr(), _multipart_form_data.size()); String s = String::utf8(_multipart_form_data.ptr(), _multipart_form_data.size());

View File

@ -34,9 +34,12 @@
#include "core/containers/vector.h" #include "core/containers/vector.h"
#include "core/string/ustring.h" #include "core/string/ustring.h"
#include "core/os/file_access.h"
#include "core/object/reference.h" #include "core/object/reference.h"
#include "web_server_simple.h"
class SimpleWebServerRequest; class SimpleWebServerRequest;
struct http_parser; struct http_parser;
struct http_parser_settings; struct http_parser_settings;
@ -54,6 +57,10 @@ public:
}; };
uint64_t max_request_size; 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<SimpleWebServerRequest> get_next_request(); Ref<SimpleWebServerRequest> get_next_request();
int get_request_count() const; int get_request_count() const;
@ -76,6 +83,10 @@ protected:
String _partial_data; String _partial_data;
uint64_t _current_request_size; uint64_t _current_request_size;
uint64_t _current_upload_files_size;
String _upload_file_full_path;
FileAccess *_upload_file_access;
Ref<SimpleWebServerRequest> _request; Ref<SimpleWebServerRequest> _request;
Vector<Ref<SimpleWebServerRequest>> _requests; Vector<Ref<SimpleWebServerRequest>> _requests;

View File

@ -586,7 +586,6 @@ HTTPServerConnection::HTTPServerConnection() {
_timeout_usec = 20 * 1000 * 1000; _timeout_usec = 20 * 1000 * 1000;
_http_parser.instance(); _http_parser.instance();
_http_parser->max_request_size = max_request_size;
time = 0; time = 0;
memset(req_buf, 0, sizeof(req_buf)); memset(req_buf, 0, sizeof(req_buf));
@ -681,8 +680,10 @@ void HTTPServerSimple::poll() {
connection->_web_server = _web_server; connection->_web_server = _web_server;
connection->_http_server = this; connection->_http_server = this;
connection->max_request_size = max_request_size;
connection->_http_parser->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->use_ssl = use_ssl;
connection->key = key; connection->key = key;
@ -842,6 +843,9 @@ HTTPServerSimple::HTTPServerSimple() {
server.instance(); server.instance();
stop(); stop();
max_request_size = 0;
request_max_file_upload_size = 0;
} }
HTTPServerSimple::~HTTPServerSimple() { HTTPServerSimple::~HTTPServerSimple() {

View File

@ -46,6 +46,8 @@
#include "modules/web/http/http_server_enums.h" #include "modules/web/http/http_server_enums.h"
#include "web_server_simple.h"
class HTTPParser; class HTTPParser;
class WebServerSimple; class WebServerSimple;
class WebServerRequest; class WebServerRequest;
@ -78,8 +80,6 @@ public:
WebServerSimple *_web_server; WebServerSimple *_web_server;
HTTPServerSimple *_http_server; HTTPServerSimple *_http_server;
uint64_t max_request_size;
bool use_ssl = false; bool use_ssl = false;
Ref<CryptoKey> key; Ref<CryptoKey> key;
Ref<X509Certificate> _certificate; Ref<X509Certificate> _certificate;
@ -126,6 +126,10 @@ public:
WebServerSimple *_web_server; WebServerSimple *_web_server;
uint64_t max_request_size; 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<StringName, String> mimes; RBMap<StringName, String> mimes;

View File

@ -43,6 +43,8 @@
#include "http_server_simple.h" #include "http_server_simple.h"
#include "modules/web/http/web_permission.h" #include "modules/web/http/web_permission.h"
#include "core/os/dir_access.h"
String SimpleWebServerRequest::get_cookie(const String &key) { String SimpleWebServerRequest::get_cookie(const String &key) {
for (int i = 0; i < _cookies.size(); ++i) { for (int i = 0; i < _cookies.size(); ++i) {
const CookieData &d = _cookies[i]; const CookieData &d = _cookies[i];
@ -58,8 +60,6 @@ HTTPServerEnums::HTTPMethod SimpleWebServerRequest::get_method() const {
return _method; return _method;
} }
void SimpleWebServerRequest::parse_files() {
}
int SimpleWebServerRequest::get_file_count() const { int SimpleWebServerRequest::get_file_count() const {
return _files.size(); return _files.size();
} }
@ -73,19 +73,62 @@ String SimpleWebServerRequest::get_file_key(const int index) const {
return _files[index].file_name; 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); 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 { PoolByteArray SimpleWebServerRequest::get_file_data(const int index) const {
ERR_FAIL_INDEX_V(index, _files.size(), PoolByteArray()); 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 { String SimpleWebServerRequest::get_file_data_str(const int index) const {
ERR_FAIL_INDEX_V(index, _files.size(), ""); ERR_FAIL_INDEX_V(index, _files.size(), "");
const FileEntry &e = _files[index];
if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) {
PoolByteArray::Read r = _files[index].data.read(); PoolByteArray::Read r = _files[index].data.read();
String ret = reinterpret_cast<const char *>(r.ptr()); String ret = reinterpret_cast<const char *>(r.ptr());
@ -95,6 +138,59 @@ String SimpleWebServerRequest::get_file_data_str(const int index) const {
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 { String SimpleWebServerRequest::get_parameter(const String &key) const {
if (!_post_parameters.has(key)) { if (!_post_parameters.has(key)) {
return get_get_parameter(key); return get_get_parameter(key);
@ -271,8 +367,9 @@ void SimpleWebServerRequest::set_host(const String &value) {
_host = 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; FileEntry e;
e.type = FileEntry::FILE_ENTRY_TYPE_MEMORY;
e.key = key; e.key = key;
e.file_name = file_name; e.file_name = file_name;
e.data = data; e.data = data;
@ -280,6 +377,16 @@ void SimpleWebServerRequest::add_file(const String &key, const String &file_name
_files.push_back(e); _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) { void SimpleWebServerRequest::add_cookie_data(const String &key, const String &value) {
CookieData d; CookieData d;
d.key = key; d.key = key;
@ -303,6 +410,20 @@ SimpleWebServerRequest::SimpleWebServerRequest() {
} }
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() { void SimpleWebServerRequest::_bind_methods() {

View File

@ -58,13 +58,14 @@ public:
virtual HTTPServerEnums::HTTPMethod get_method() const; virtual HTTPServerEnums::HTTPMethod get_method() const;
virtual void parse_files();
virtual int get_file_count() const; virtual int get_file_count() const;
virtual String get_file_file_name(const int index) const; virtual String get_file_file_name(const int index) const;
virtual String get_file_key(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 PoolByteArray get_file_data(const int index) const;
virtual String get_file_data_str(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_parameter(const String &key) const;
virtual String get_post_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const;
@ -93,7 +94,8 @@ public:
void set_parser_path(const String &value); void set_parser_path(const String &value);
void set_host(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); void add_cookie_data(const String &key, const String &value);
@ -121,9 +123,22 @@ protected:
String _host; String _host;
struct FileEntry { struct FileEntry {
enum FileEntryType {
FILE_ENTRY_TYPE_MEMORY = 0,
FILE_ENTRY_TYPE_TEMP_FILE = 0,
};
mutable bool moved;
FileEntryType type;
String file_name; String file_name;
PoolByteArray data; PoolByteArray data;
String key; //form name key String key; //form name key
mutable String path;
FileEntry() {
moved = false;
}
}; };
Vector<FileEntry> _files; Vector<FileEntry> _files;

View File

@ -129,6 +129,37 @@ void WebServerSimple::set_max_request_size(const int val) {
_apply_max_request_size_type(); _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) { void WebServerSimple::add_mime_type(const String &file_extension, const String &mime_type) {
_server->mimes[file_extension] = mime_type; _server->mimes[file_extension] = mime_type;
} }
@ -145,6 +176,9 @@ void WebServerSimple::_start() {
WebServer::_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()) { if (!OS::get_singleton()->can_use_threads()) {
_server->_use_worker_threads = false; _server->_use_worker_threads = false;
} else { } else {
@ -231,6 +265,11 @@ WebServerSimple::WebServerSimple() {
_max_request_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE; _max_request_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE;
_max_request_size = 3; _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_port = 8080;
_bind_host = "0.0.0.0"; _bind_host = "0.0.0.0";
@ -251,6 +290,7 @@ WebServerSimple::WebServerSimple() {
_server->_web_server = this; _server->_web_server = this;
_apply_max_request_size_type(); _apply_max_request_size_type();
_apply_request_max_file_upload_size_type();
} }
WebServerSimple::~WebServerSimple() { WebServerSimple::~WebServerSimple() {
@ -267,6 +307,22 @@ void WebServerSimple::_apply_max_request_size_type() {
_server->max_request_size = (static_cast<uint64_t>(1) << (10 * static_cast<uint64_t>(_max_request_size_type))) * static_cast<uint64_t>(_max_request_size); _server->max_request_size = (static_cast<uint64_t>(1) << (10 * static_cast<uint64_t>(_max_request_size_type))) * static_cast<uint64_t>(_max_request_size);
} }
void WebServerSimple::_apply_request_max_file_upload_size_type() {
_server->request_max_file_upload_size = (static_cast<uint64_t>(1) << (10 * static_cast<uint64_t>(_upload_request_max_file_size_type))) * static_cast<uint64_t>(_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) { void WebServerSimple::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_INTERNAL_PROCESS: { 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); 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_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("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); 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_KILO_BYTE);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_MEGA_BYTE); BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_MEGA_BYTE);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_GIGA_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) { void WebServerSimple::_server_thread_poll(void *data) {

View File

@ -56,6 +56,12 @@ public:
MAX_REQUEST_SIZE_TYPE_GIGA_BYTE = 3, 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(); int get_bind_port();
void set_bind_port(const int val); void set_bind_port(const int val);
@ -86,15 +92,26 @@ public:
MaxRequestSizeTypes get_max_request_size_type(); MaxRequestSizeTypes get_max_request_size_type();
void set_max_request_size_type(const MaxRequestSizeTypes val); void set_max_request_size_type(const MaxRequestSizeTypes val);
// Note, that the implementation is extremely simple for now. // This includes the entire request header,
// This includes the entire request header, including file uploads, // including file uploads (only if they are stored in memory) because
// as right now uploaded files are stored in memory, // then a big file upload / request can eat all the ram in a server!
// so this will not change until temp files are implemented.
// (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). // Also 0 means 0, not unlimited -> This should NOT change (Reason: line above).
int get_max_request_size(); int get_max_request_size();
void set_max_request_size(const int val); 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 add_mime_type(const String &file_extension, const String &mime_type);
void remove_mime_type(const String &file_extension); void remove_mime_type(const String &file_extension);
@ -110,7 +127,9 @@ public:
protected: protected:
void _apply_max_request_size_type(); 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); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
@ -120,7 +139,6 @@ protected:
bool _start_on_ready; bool _start_on_ready;
//TODO add binds to set path
bool _use_ssl; bool _use_ssl;
String _ssl_key; String _ssl_key;
String _ssl_cert; String _ssl_cert;
@ -134,6 +152,11 @@ protected:
MaxRequestSizeTypes _max_request_size_type; MaxRequestSizeTypes _max_request_size_type;
int _max_request_size; 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<HTTPServerSimple> _server; Ref<HTTPServerSimple> _server;
bool _server_quit; bool _server_quit;
Mutex _server_lock; Mutex _server_lock;
@ -144,5 +167,6 @@ protected:
}; };
VARIANT_ENUM_CAST(WebServerSimple::MaxRequestSizeTypes); VARIANT_ENUM_CAST(WebServerSimple::MaxRequestSizeTypes);
VARIANT_ENUM_CAST(WebServerSimple::FileUploadStoreType);
#endif #endif

View File

@ -45,8 +45,6 @@ HTTPServerEnums::HTTPMethod WebNodeEditorWebServerRequest::get_method() const {
return HTTPServerEnums::HTTP_METHOD_GET; return HTTPServerEnums::HTTP_METHOD_GET;
} }
void WebNodeEditorWebServerRequest::parse_files() {
}
int WebNodeEditorWebServerRequest::get_file_count() const { int WebNodeEditorWebServerRequest::get_file_count() const {
return 0; 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 { String WebNodeEditorWebServerRequest::get_file_key(const int index) const {
return ""; return "";
} }
int WebNodeEditorWebServerRequest::get_file_length(const int index) const { uint64_t WebNodeEditorWebServerRequest::get_file_length(const int index) const {
return 0; return 0;
} }
PoolByteArray WebNodeEditorWebServerRequest::get_file_data(const int index) const { PoolByteArray WebNodeEditorWebServerRequest::get_file_data(const int index) const {

View File

@ -61,11 +61,10 @@ public:
HTTPServerEnums::HTTPMethod get_method() const; HTTPServerEnums::HTTPMethod get_method() const;
void parse_files();
int get_file_count() const; int get_file_count() const;
String get_file_file_name(const int index) const; String get_file_file_name(const int index) const;
String get_file_key(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; PoolByteArray get_file_data(const int index) const;
String get_file_data_str(const int index) const; String get_file_data_str(const int index) const;

View File

@ -246,8 +246,6 @@ HTTPServerEnums::HTTPMethod WebServerRequest::get_method() const {
return HTTPServerEnums::HTTP_METHOD_GET; return HTTPServerEnums::HTTP_METHOD_GET;
} }
void WebServerRequest::parse_files() {
}
int WebServerRequest::get_file_count() const { int WebServerRequest::get_file_count() const {
return 0; 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 { String WebServerRequest::get_file_key(const int index) const {
return String(); return String();
} }
int WebServerRequest::get_file_length(const int index) const { uint64_t WebServerRequest::get_file_length(const int index) const {
return 0; return 0;
} }
PoolByteArray WebServerRequest::get_file_data(const int index) const { 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 { String WebServerRequest::get_file_data_str(const int index) const {
return String(); 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 { String WebServerRequest::get_parameter(const String &key) const {
return String(); 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("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_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_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_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_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", "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("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_parameter", "key"), &WebServerRequest::get_parameter);
ClassDB::bind_method(D_METHOD("get_post_parameter", "key"), &WebServerRequest::get_post_parameter); ClassDB::bind_method(D_METHOD("get_post_parameter", "key"), &WebServerRequest::get_post_parameter);

View File

@ -110,13 +110,14 @@ public:
virtual HTTPServerEnums::HTTPMethod get_method() const; virtual HTTPServerEnums::HTTPMethod get_method() const;
virtual void parse_files();
virtual int get_file_count() const; virtual int get_file_count() const;
virtual String get_file_file_name(const int index) const; virtual String get_file_file_name(const int index) const;
virtual String get_file_key(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 PoolByteArray get_file_data(const int index) const;
virtual String get_file_data_str(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_parameter(const String &key) const;
virtual String get_post_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const;

View File

@ -44,9 +44,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::get_method() const {
return static_cast<HTTPServerEnums::HTTPMethod>(m); return static_cast<HTTPServerEnums::HTTPMethod>(m);
} }
void WebServerRequestScriptable::parse_files() {
call("_parse_files");
}
int WebServerRequestScriptable::get_file_count() const { int WebServerRequestScriptable::get_file_count() const {
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_count"); return const_cast<WebServerRequestScriptable *>(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 { String WebServerRequestScriptable::get_file_key(const int index) const {
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_key", index); return const_cast<WebServerRequestScriptable *>(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<WebServerRequestScriptable *>(this)->call("_get_file_length", index); return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_length", index);
} }
PoolByteArray WebServerRequestScriptable::get_file_data(const int index) const { 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 { String WebServerRequestScriptable::get_file_data_str(const int index) const {
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_data_str", index); return const_cast<WebServerRequestScriptable *>(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<WebServerRequestScriptable *>(this)->call("_is_file_moved", index);
}
String WebServerRequestScriptable::get_parameter(const String &key) const { String WebServerRequestScriptable::get_parameter(const String &key) const {
return const_cast<WebServerRequestScriptable *>(this)->call("_get_parameter", key); return const_cast<WebServerRequestScriptable *>(this)->call("_get_parameter", key);
@ -155,8 +158,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::_get_method() const {
return HTTPServerEnums::HTTP_METHOD_GET; return HTTPServerEnums::HTTP_METHOD_GET;
} }
void WebServerRequestScriptable::_parse_files() {
}
int WebServerRequestScriptable::_get_file_count() const { int WebServerRequestScriptable::_get_file_count() const {
return 0; 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 { String WebServerRequestScriptable::_get_file_data_str(const int index) const {
return String(); 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 { String WebServerRequestScriptable::_get_parameter(const String &key) const {
return String(); return String();
@ -295,13 +302,14 @@ void WebServerRequestScriptable::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_method")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_method"));
BIND_VMETHOD(MethodInfo("_parse_files"));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_file_count")); 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_file_name", PropertyInfo(Variant::INT, "index")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_key", 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::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::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::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_parameter", PropertyInfo(Variant::STRING, "key")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_post_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("_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_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_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_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_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", "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("_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_parameter", "key"), &WebServerRequestScriptable::_get_parameter);
ClassDB::bind_method(D_METHOD("_get_post_parameter", "key"), &WebServerRequestScriptable::_get_post_parameter); ClassDB::bind_method(D_METHOD("_get_post_parameter", "key"), &WebServerRequestScriptable::_get_post_parameter);

View File

@ -57,13 +57,14 @@ public:
virtual HTTPServerEnums::HTTPMethod get_method() const; virtual HTTPServerEnums::HTTPMethod get_method() const;
virtual void parse_files();
virtual int get_file_count() const; virtual int get_file_count() const;
virtual String get_file_file_name(const int index) const; virtual String get_file_file_name(const int index) const;
virtual String get_file_key(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 PoolByteArray get_file_data(const int index) const;
virtual String get_file_data_str(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_parameter(const String &key) const;
virtual String get_post_parameter(const String &key) const; virtual String get_post_parameter(const String &key) const;
@ -98,13 +99,14 @@ public:
virtual HTTPServerEnums::HTTPMethod _get_method() const; virtual HTTPServerEnums::HTTPMethod _get_method() const;
virtual void _parse_files();
virtual int _get_file_count() const; virtual int _get_file_count() const;
virtual String _get_file_file_name(const int index) const; virtual String _get_file_file_name(const int index) const;
virtual String _get_file_key(const int index) const; virtual String _get_file_key(const int index) const;
virtual int _get_file_length(const int index) const; virtual int _get_file_length(const int index) const;
virtual PoolByteArray _get_file_data(const int index) const; virtual PoolByteArray _get_file_data(const int index) const;
virtual String _get_file_data_str(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_parameter(const String &key) const;
virtual String _get_post_parameter(const String &key) const; virtual String _get_post_parameter(const String &key) const;