aboutsummaryrefslogtreecommitdiff
path: root/backends/networking/sdl_net
diff options
context:
space:
mode:
Diffstat (limited to 'backends/networking/sdl_net')
-rw-r--r--backends/networking/sdl_net/indexpagehandler.cpp134
-rw-r--r--backends/networking/sdl_net/indexpagehandler.h24
2 files changed, 156 insertions, 2 deletions
diff --git a/backends/networking/sdl_net/indexpagehandler.cpp b/backends/networking/sdl_net/indexpagehandler.cpp
index c2ea470802..c44c3d4a5a 100644
--- a/backends/networking/sdl_net/indexpagehandler.cpp
+++ b/backends/networking/sdl_net/indexpagehandler.cpp
@@ -22,9 +22,11 @@
#include "backends/networking/sdl_net/indexpagehandler.h"
#include "backends/networking/sdl_net/localwebserver.h"
+#include "backends/saves/default/default-saves.h"
#include "common/archive.h"
#include "common/config-manager.h"
#include "common/file.h"
+#include "common/savefile.h"
#include "common/translation.h"
#include "common/unzip.h"
#include "gui/storagewizarddialog.h"
@@ -71,15 +73,28 @@ void IndexPageHandler::handle(Client &client) {
}
void IndexPageHandler::handleFiles(Client &client) {
- Common::String response = "<html><head><title>ScummVM</title></head><body>{content}</body></html>"; //TODO
+ 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?
// load stylish response page from the archive
Common::SeekableReadStream *const stream = getArchiveFile(FILES_PAGE_NAME);
if (stream) response = readEverythingFromStream(stream);
- // TODO: list specified directory
Common::String path = client.queryParameter("path");
Common::String content = "";
+
+ // show an error message if failed to list directory
+ if (!listDirectory(path, content, itemTemplate)) {
+ handleErrorMessage(
+ client,
+ Common::String::format(
+ "%s<br/><a href=\"files?path=/\">%s</a>",
+ _("ScummVM couldn't list the directory you specified."),
+ _("Back to the files manager")
+ )
+ );
+ return;
+ }
//these occur twice:
replace(response, "{create_directory_button}", _("Create directory"));
@@ -98,6 +113,121 @@ void IndexPageHandler::handleResource(Client &client) {
LocalWebserver::setClientGetHandler(client, getArchiveFile(filename), 200, LocalWebserver::determineMimeType(filename));
}
+void IndexPageHandler::handleErrorMessage(Client &client, Common::String message) {
+ Common::String response = "<html><head><title>ScummVM</title></head><body>{message}</body></html>";
+
+ // load stylish response page from the archive
+ Common::SeekableReadStream *const stream = getArchiveFile(INDEX_PAGE_NAME);
+ if (stream) response = readEverythingFromStream(stream);
+
+ replace(response, "{message}", message);
+ LocalWebserver::setClientGetHandler(client, response);
+}
+
+/// "files/"-related
+
+Common::String IndexPageHandler::parentPath(Common::String path) {
+ if (path.size() && (path.lastChar() == '/' || path.lastChar() == '\\')) path.deleteLastChar();
+ if (!path.empty()) {
+ for (int i = path.size() - 1; i >= 0; --i)
+ if (i == 0 || path[i] == '/' || path[i] == '\\') {
+ path.erase(i);
+ break;
+ }
+ }
+ if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/';
+ return path;
+}
+
+void IndexPageHandler::addItem(Common::String &content, const Common::String &itemTemplate, bool isDirectory, Common::String path, Common::String name, Common::String size) {
+ Common::String item = itemTemplate;
+ replace(item, "{link}", (isDirectory ? "files?path=" : "download?path=") + path);
+ replace(item, "{name}", name);
+ replace(item, "{size}", size);
+ content += item;
+}
+
+bool IndexPageHandler::listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate) {
+ if (path == "" || path == "/") {
+ addItem(content, itemTemplate, true, "/root/", _("File system root"));
+ addItem(content, itemTemplate, true, "/saves/", _("Saved games"));
+ return true;
+ }
+
+ Common::String prefixToRemove = "", prefixToAdd = "";
+ if (!transformPath(path, prefixToRemove, prefixToAdd)) return false;
+
+ Common::FSNode node = Common::FSNode(path);
+ if (path == "/") node = node.getParent(); // absolute root
+ if (!node.isDirectory()) return false;
+
+ // list directory
+ Common::FSList _nodeContent;
+ if (!node.getChildren(_nodeContent, Common::FSNode::kListAll, false)) // do not show hidden files
+ _nodeContent.clear();
+ else
+ Common::sort(_nodeContent.begin(), _nodeContent.end());
+
+ // add parent directory link
+ {
+ Common::String filePath = path;
+ if (filePath.hasPrefix(prefixToRemove))
+ filePath.erase(0, prefixToRemove.size());
+ if (filePath == "" || filePath == "/" || filePath == "\\")
+ filePath = "/";
+ else
+ filePath = parentPath(prefixToAdd + filePath);
+ addItem(content, itemTemplate, true, filePath, _("Parent directory"));
+ }
+
+ // fill the content
+ for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
+ Common::String name = i->getDisplayName();
+ if (i->isDirectory()) name += "/";
+
+ Common::String filePath = i->getPath();
+ if (filePath.hasPrefix(prefixToRemove))
+ filePath.erase(0, prefixToRemove.size());
+ filePath = prefixToAdd + filePath;
+
+ addItem(content, itemTemplate, i->isDirectory(), filePath, name);
+ }
+
+ return true;
+}
+
+bool IndexPageHandler::transformPath(Common::String &path, Common::String &prefixToRemove, Common::String &prefixToAdd) {
+ // <path> is not empty, but could lack the trailing slash
+ if (path.lastChar() != '/' && path.lastChar() != '\\') path += '/';
+
+ if (path.hasPrefix("/root")) {
+ prefixToAdd = "/root/";
+ prefixToRemove = "";
+ path.erase(0, 5);
+ if (path == "") path = "/"; // absolute root is '/'
+ if (path != "/") path.deleteChar(0); // if that was "/root/ab/c", it becomes "/ab/c", but we need "ab/c"
+ return true;
+ }
+
+ if (path.hasPrefix("/saves")) {
+ prefixToAdd = "/saves/";
+
+ // determine savepath (prefix to remove)
+ DefaultSaveFileManager *manager = dynamic_cast<DefaultSaveFileManager *>(g_system->getSavefileManager());
+ prefixToRemove = (manager ? manager->concatWithSavesPath("") : ConfMan.get("savepath"));
+ if (prefixToRemove.size() && prefixToRemove.lastChar() != '/' && prefixToRemove.lastChar() != '\\')
+ prefixToRemove += '/';
+
+ path.erase(0, 6);
+ if (path.size() && (path[0] == '/' || path[0] == '\\'))
+ path.deleteChar(0);
+ path = prefixToRemove + path;
+ return true;
+ }
+
+ return false;
+}
+
/// public
void IndexPageHandler::addPathHandler(LocalWebserver &server) {
diff --git a/backends/networking/sdl_net/indexpagehandler.h b/backends/networking/sdl_net/indexpagehandler.h
index e70ffd5236..0ccbf32480 100644
--- a/backends/networking/sdl_net/indexpagehandler.h
+++ b/backends/networking/sdl_net/indexpagehandler.h
@@ -36,6 +36,30 @@ class IndexPageHandler: public GUI::CommandSender {
void handle(Client &client);
void handleFiles(Client &client);
void handleResource(Client &client);
+ void handleErrorMessage(Client &client, Common::String message);
+
+ // "files/"-related
+ Common::String parentPath(Common::String path);
+
+ /** Helper method for adding items into the files list. */
+ void addItem(Common::String &content, const Common::String &itemTemplate, bool isDirectory, Common::String path, Common::String name, Common::String size = "");
+
+ /**
+ * Lists the directory <path>.
+ *
+ * Returns true on success.
+ */
+ bool listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate);
+
+ /**
+ * Transforms virtual <path> into actual file system path.
+ *
+ * Fills prefixes with actual file system prefix ("to remove")
+ * and virtual path prefix ("to add").
+ *
+ * Returns true on success.
+ */
+ bool transformPath(Common::String &path, Common::String &prefixToRemove, Common::String &prefixToAdd);
void replace(Common::String &source, const Common::String &what, const Common::String &with);
Common::Archive *getZipArchive();