aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/networking/sdl_net/client.cpp5
-rw-r--r--backends/networking/sdl_net/handlers/filespagehandler.cpp73
-rw-r--r--backends/networking/sdl_net/handlers/filespagehandler.h11
-rw-r--r--backends/networking/sdl_net/localwebserver.cpp29
-rw-r--r--backends/networking/sdl_net/localwebserver.h1
-rw-r--r--backends/networking/wwwroot.zipbin230886 -> 231000 bytes
-rw-r--r--backends/networking/wwwroot/.files.html2
7 files changed, 119 insertions, 2 deletions
diff --git a/backends/networking/sdl_net/client.cpp b/backends/networking/sdl_net/client.cpp
index 67b45b6cbe..f567891dd8 100644
--- a/backends/networking/sdl_net/client.cpp
+++ b/backends/networking/sdl_net/client.cpp
@@ -23,6 +23,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/networking/sdl_net/client.h"
+#include "backends/networking/sdl_net/localwebserver.h"
#include "common/textconsole.h"
#include <SDL/SDL_net.h>
@@ -201,13 +202,13 @@ Common::String Client::queryParameter(Common::String name) const {
} else key += _query[i];
} else {
if (_query[i] == '&') {
- if (key == name) return value;
+ if (key == name) return LocalWebserver::urlDecode(value);
readingKey = true;
key = "";
} else value += _query[i];
}
}
- if (key == name) return value; //the last key doesn't have an '&' in the end of the query
+ if (key == name) return LocalWebserver::urlDecode(value); //the last key doesn't have an '&' in the end of the query
return "";
}
diff --git a/backends/networking/sdl_net/handlers/filespagehandler.cpp b/backends/networking/sdl_net/handlers/filespagehandler.cpp
index 360fe201b8..327071fc11 100644
--- a/backends/networking/sdl_net/handlers/filespagehandler.cpp
+++ b/backends/networking/sdl_net/handlers/filespagehandler.cpp
@@ -22,6 +22,7 @@
#include "backends/networking/sdl_net/handlers/filespagehandler.h"
#include "backends/networking/sdl_net/localwebserver.h"
+#include "backends/fs/fs-factory.h"
#include "common/file.h"
#include "common/translation.h"
@@ -35,6 +36,11 @@ FilesPageHandler::FilesPageHandler() {}
FilesPageHandler::~FilesPageHandler() {}
void FilesPageHandler::handle(Client &client) {
+ if (client.path() == "/files") handleFiles(client);
+ else handleCreateDirectory(client);
+}
+
+void FilesPageHandler::handleFiles(Client &client) {
Common::String response = "<html><head><title>ScummVM</title></head><body><table>{content}</table></body></html>"; //TODO: add controls
Common::String itemTemplate = "<tr><td><a href=\"{link}\">{name}</a></td><td>{size}</td></tr>\n"; //TODO: load this template too?
@@ -61,6 +67,8 @@ void FilesPageHandler::handle(Client &client) {
//these occur twice:
replace(response, "{create_directory_button}", _("Create directory"));
replace(response, "{create_directory_button}", _("Create directory"));
+ replace(response, "{path}", client.queryParameter("path"));
+ replace(response, "{path}", client.queryParameter("path"));
replace(response, "{upload_files_button}", _("Upload files")); //tab
replace(response, "{upload_file_button}", _("Upload files")); //button in the tab
replace(response, "{create_directory_desc}", _("Type new directory name:"));
@@ -69,6 +77,27 @@ void FilesPageHandler::handle(Client &client) {
LocalWebserver::setClientGetHandler(client, response);
}
+void FilesPageHandler::handleCreateDirectory(Client &client) {
+ Common::String path = client.queryParameter("path");
+ Common::String name = client.queryParameter("directory_name");
+ Common::String errorMessage = "";
+
+ // show an error message if failed to create directory
+ if (!createDirectory(path, name, errorMessage)) {
+ handleErrorMessage(
+ client,
+ Common::String::format(
+ "%s<br/><a href=\"files?path=/\">%s</a>",
+ errorMessage.c_str(),
+ _("Back to the files manager")
+ )
+ );
+ return;
+ }
+
+ handleFiles(client);
+}
+
void FilesPageHandler::handleErrorMessage(Client &client, Common::String message) {
Common::String response = "<html><head><title>ScummVM</title></head><body>{message}</body></html>";
@@ -80,6 +109,50 @@ void FilesPageHandler::handleErrorMessage(Client &client, Common::String message
LocalWebserver::setClientGetHandler(client, response);
}
+bool FilesPageHandler::createDirectory(Common::String path, Common::String name, Common::String &errorMessage) {
+ // check that <path> is not an absolute root
+ if (path == "" || path == "/") {
+ errorMessage = _("Can't create directory here!");
+ return false;
+ }
+
+ // transform virtual path to actual file system one
+ Common::String prefixToRemove = "", prefixToAdd = "";
+ if (!transformPath(path, prefixToRemove, prefixToAdd) || path.empty()) {
+ errorMessage = _("Invalid path!");
+ return false;
+ }
+
+ // check that <path> exists and is directory
+ AbstractFSNode *node = g_system->getFilesystemFactory()->makeFileNodePath(path);
+ if (!node->exists()) {
+ errorMessage = _("Parent directory doesn't exists!");
+ return false;
+ }
+ if (!node->isDirectory()) {
+ errorMessage = _("Can't create a directory within a file!");
+ return false;
+ }
+
+ // check that <directory_name> doesn't exist or is directory
+ if (path.lastChar() != '/' && path.lastChar() != '\\') path += '/';
+ node = g_system->getFilesystemFactory()->makeFileNodePath(path + name);
+ if (node->exists()) {
+ if (!node->isDirectory()) {
+ errorMessage = _("There is a file with that name in the parent directory!");
+ return false;
+ } else return true;
+ }
+
+ // create the <directory_name> in <path>
+ if (!node->create(true)) {
+ errorMessage = _("Failed to create the directory!");
+ return false;
+ }
+
+ return true;
+}
+
bool FilesPageHandler::listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate) {
if (path == "" || path == "/") {
addItem(content, itemTemplate, true, "/root/", _("File system root"));
diff --git a/backends/networking/sdl_net/handlers/filespagehandler.h b/backends/networking/sdl_net/handlers/filespagehandler.h
index 6205dcd52c..e5a32c98b0 100644
--- a/backends/networking/sdl_net/handlers/filespagehandler.h
+++ b/backends/networking/sdl_net/handlers/filespagehandler.h
@@ -29,9 +29,20 @@ namespace Networking {
class FilesPageHandler: public FilesBaseHandler {
void handle(Client &client);
+ void handleFiles(Client &client);
+ void handleCreateDirectory(Client &client);
void handleErrorMessage(Client &client, Common::String message);
/**
+ * Creates the directory <name> in <path>.
+ *
+ * Fills <errorMessage> on failure.
+ *
+ * Returns true on success.
+ */
+ bool createDirectory(Common::String path, Common::String name, Common::String &errorMessage);
+
+ /**
* Lists the directory <path>.
*
* Returns true on success.
diff --git a/backends/networking/sdl_net/localwebserver.cpp b/backends/networking/sdl_net/localwebserver.cpp
index c3df9f8819..c8f322dad6 100644
--- a/backends/networking/sdl_net/localwebserver.cpp
+++ b/backends/networking/sdl_net/localwebserver.cpp
@@ -44,6 +44,7 @@ LocalWebserver::LocalWebserver(): _set(nullptr), _serverSocket(nullptr), _timerS
_stopOnIdle(false), _clients(0), _idlingFrames(0) {
addPathHandler("/", _indexPageHandler.getHandler());
addPathHandler("/files", _filesPageHandler.getHandler());
+ addPathHandler("/create", _filesPageHandler.getHandler()); //"Create directory" feature
_defaultHandler = _resourceHandler.getHandler();
}
@@ -271,4 +272,32 @@ const char *LocalWebserver::determineMimeType(Common::String &filename) {
return "application/octet-stream";
}
+namespace {
+int hexDigit(char c) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if ('A' <= c && c <= 'F') return c - 'A' + 10;
+ if ('a' <= c && c <= 'f') return c - 'a' + 10;
+ return -1;
+}
+}
+
+Common::String LocalWebserver::urlDecode(Common::String value) {
+ Common::String result = "";
+ uint32 size = value.size();
+ for (uint32 i = 0; i < size; ++i) {
+ if (value[i] == '%' && i+2 < size) {
+ int d1 = hexDigit(value[i+1]);
+ int d2 = hexDigit(value[i+2]);
+ if (0 <= d1 && d1 < 16 && 0 <= d2 && d2 < 16) {
+ result += (char)(d1 * 16 + d2);
+ i = i + 2;
+ continue;
+ }
+ }
+
+ result += value[i];
+ }
+ return result;
+}
+
} // End of namespace Networking
diff --git a/backends/networking/sdl_net/localwebserver.h b/backends/networking/sdl_net/localwebserver.h
index 1d397e6dcc..2e56209ab0 100644
--- a/backends/networking/sdl_net/localwebserver.h
+++ b/backends/networking/sdl_net/localwebserver.h
@@ -87,6 +87,7 @@ public:
static void setClientGetHandler(Client &client, Common::String response, long code = 200, const char *mimeType = nullptr);
static void setClientGetHandler(Client &client, Common::SeekableReadStream *responseStream, long code = 200, const char *mimeType = nullptr);
static const char *determineMimeType(Common::String &filename);
+ static Common::String urlDecode(Common::String value);
};
/** Shortcut for accessing the local webserver. */
diff --git a/backends/networking/wwwroot.zip b/backends/networking/wwwroot.zip
index 4d1be97524..de683a05d4 100644
--- a/backends/networking/wwwroot.zip
+++ b/backends/networking/wwwroot.zip
Binary files differ
diff --git a/backends/networking/wwwroot/.files.html b/backends/networking/wwwroot/.files.html
index 2baf4a02dc..de29ac3fa3 100644
--- a/backends/networking/wwwroot/.files.html
+++ b/backends/networking/wwwroot/.files.html
@@ -18,6 +18,7 @@
<div id="create_directory" class="modal">
<p>{create_directory_desc}</p>
<form action="create">
+ <input type="hidden" name="path" value="{path}"/>
<input type="text" name="directory_name" value=""/>
<input type="submit" value="{create_directory_button}"/>
</form>
@@ -25,6 +26,7 @@
<div id="upload_file" class="modal">
<p>{upload_file_desc}</p>
<form action="upload" method="post">
+ <input type="hidden" name="path" value="{path}"/>
<input type="file" name="upload_file"/>
<input type="submit" value="{upload_file_button}"/>
</form>