-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remote ISO: Allow sharing a full folder instead of Recent #18632
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,10 +22,12 @@ | |
#include "Common/Net/HTTPClient.h" | ||
#include "Common/Net/HTTPServer.h" | ||
#include "Common/Net/Sinks.h" | ||
#include "Common/Net/URL.h" | ||
#include "Common/Thread/ThreadUtil.h" | ||
#include "Common/Log.h" | ||
#include "Common/File/FileUtil.h" | ||
#include "Common/File/FileDescriptor.h" | ||
#include "Common/File/DirListing.h" | ||
#include "Common/File/VFS/VFS.h" | ||
#include "Common/TimeUtil.h" | ||
#include "Common/StringUtils.h" | ||
|
@@ -49,6 +51,16 @@ static ServerStatus serverStatus; | |
static std::mutex serverStatusLock; | ||
static int serverFlags; | ||
|
||
// NOTE: These *only* encode spaces, which is really enough. | ||
|
||
std::string ServerUriEncode(std::string_view plain) { | ||
return ReplaceAll(plain, " ", "%20"); | ||
} | ||
|
||
std::string ServerUriDecode(std::string_view encoded) { | ||
return ReplaceAll(encoded, "%20", " "); | ||
} | ||
|
||
static void UpdateStatus(ServerStatus s) { | ||
std::lock_guard<std::mutex> guard(serverStatusLock); | ||
serverStatus = s; | ||
|
@@ -130,6 +142,12 @@ bool RemoteISOFileSupported(const std::string &filename) { | |
} | ||
|
||
static std::string RemotePathForRecent(const std::string &filename) { | ||
Path path(filename); | ||
if (path.Type() == PathType::HTTP) { | ||
// Don't re-share HTTP files from some other device. | ||
return std::string(); | ||
} | ||
|
||
#ifdef _WIN32 | ||
static const std::string sep = "\\/"; | ||
#else | ||
|
@@ -147,19 +165,30 @@ static std::string RemotePathForRecent(const std::string &filename) { | |
// Let's not serve directories, since they won't work. Only single files. | ||
// Maybe can do PBPs and other files later. Would be neat to stream virtual disc filesystems. | ||
if (RemoteISOFileSupported(basename)) { | ||
return ReplaceAll(basename, " ", "%20"); | ||
return ServerUriEncode(basename); | ||
} | ||
return ""; | ||
|
||
return std::string(); | ||
} | ||
|
||
static Path LocalFromRemotePath(const std::string &path) { | ||
for (const std::string &filename : g_Config.RecentIsos()) { | ||
std::string basename = RemotePathForRecent(filename); | ||
if (basename == path) { | ||
return Path(filename); | ||
switch ((RemoteISOShareType)g_Config.iRemoteISOShareType) { | ||
case RemoteISOShareType::RECENT: | ||
for (const std::string &filename : g_Config.RecentIsos()) { | ||
std::string basename = RemotePathForRecent(filename); | ||
if (basename == path) { | ||
return Path(filename); | ||
} | ||
} | ||
return Path(); | ||
case RemoteISOShareType::LOCAL_FOLDER: | ||
{ | ||
std::string decoded = ServerUriDecode(path); | ||
return Path(g_Config.sRemoteISOSharedDir) / decoded; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably technically a security gap. The Recent path is intentionally a bit careful to only take the filename-part, and not take for example "../../../passwd". I guess this is probably fine as hopefully you're only on a network with devices you trust... -[Unknown] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah... Probably worth adding checks against though indeed. |
||
} | ||
default: | ||
return Path(); | ||
} | ||
return Path(); | ||
} | ||
|
||
static void DiscHandler(const http::ServerRequest &request, const Path &filename) { | ||
|
@@ -226,12 +255,30 @@ static void HandleListing(const http::ServerRequest &request) { | |
request.WriteHttpResponseHeader("1.0", 200, -1, "text/plain"); | ||
request.Out()->Printf("/\n"); | ||
if (serverFlags & (int)WebServerFlags::DISCS) { | ||
// List the current discs in their recent order. | ||
for (const std::string &filename : g_Config.RecentIsos()) { | ||
std::string basename = RemotePathForRecent(filename); | ||
if (!basename.empty()) { | ||
request.Out()->Printf("%s\n", basename.c_str()); | ||
switch ((RemoteISOShareType)g_Config.iRemoteISOShareType) { | ||
case RemoteISOShareType::RECENT: | ||
// List the current discs in their recent order. | ||
for (const std::string &filename : g_Config.RecentIsos()) { | ||
std::string basename = RemotePathForRecent(filename); | ||
if (!basename.empty()) { | ||
request.Out()->Printf("%s\n", basename.c_str()); | ||
} | ||
} | ||
break; | ||
case RemoteISOShareType::LOCAL_FOLDER: | ||
{ | ||
std::vector<File::FileInfo> entries; | ||
File::GetFilesInDir(Path(g_Config.sRemoteISOSharedDir), &entries); | ||
for (const auto &entry : entries) { | ||
// TODO: Support browsing into subdirs. How are folders marked? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Folders have a trailing slash. But I can't remember if browsing supports them... I kinda think it does? It wouldn't be hard to anyway. People will probably expect this to be recursive or else to support folders (my personal preference would be folders to work.) -[Unknown] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I will add folder support later. I didn't think about the trailing slash - that'll be enough, and I'll make sure it works if it doesn't already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, let's hope the user doesn't have a subfolder called "debugger". Since /debugger is handled separately :) We're gonna have to use FallbackHandler to handle subfolder requests. |
||
if (entry.isDirectory || !RemoteISOFileSupported(entry.name)) { | ||
continue; | ||
} | ||
std::string encoded = ServerUriEncode(entry.name); | ||
request.Out()->Printf("%s\n", encoded.c_str()); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
if (serverFlags & (int)WebServerFlags::DEBUGGER) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, you also want to ecnode at least %. A filename with "%20" in it (such as a downloaded file) will not work.
-[Unknown]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, true. Just doing what the old Recent code does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, and I did first use UriDecode, but some logic broke because it encoded slashes. Should maybe fix the root cause of that instead maybe, but could also simply not encode slashes to keep compatibilty with older versions.