Skip to content

Commit

Permalink
Merge pull request #18639 from hrydgard/handle-serving-directories
Browse files Browse the repository at this point in the history
Various changes to the webserver to handle serving HTTP subfolders
  • Loading branch information
unknownbrackets committed Dec 29, 2023
2 parents 593955a + 9bcb858 commit a945682
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Common/UI/PopupScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ std::string FolderChooserChoice::ValueText() const {
return di->T("Default");
}
Path path(*value_);
return path.GetFilename();
return path.ToVisualString();
}

} // namespace
45 changes: 38 additions & 7 deletions Core/WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static ServerStatus serverStatus;
static std::mutex serverStatusLock;
static int serverFlags;

// NOTE: These *only* encode spaces, which is really enough.
// NOTE: These *only* encode spaces, which is almost enough.

std::string ServerUriEncode(std::string_view plain) {
return ReplaceAll(plain, " ", "%20");
Expand Down Expand Up @@ -182,6 +182,19 @@ static Path LocalFromRemotePath(const std::string &path) {
case RemoteISOShareType::LOCAL_FOLDER:
{
std::string decoded = ServerUriDecode(path);

if (decoded.empty() || decoded.front() != '/') {
return Path();
}

// First reject backslashes, in case of any Windows shenanigans.
if (decoded.find('\\') != std::string::npos) {
return Path();
}
// Then, reject slashes combined with ".." to prevent directory traversal. Hope this is enough.
if (decoded.find("/..") != std::string::npos) {
return Path();
}
return Path(g_Config.sRemoteISOSharedDir) / decoded;
}
default:
Expand Down Expand Up @@ -266,13 +279,21 @@ static void HandleListing(const http::ServerRequest &request) {
case RemoteISOShareType::LOCAL_FOLDER:
{
std::vector<File::FileInfo> entries;
File::GetFilesInDir(Path(g_Config.sRemoteISOSharedDir), &entries);

std::string resource = request.resource();
Path localDir = LocalFromRemotePath(resource);

File::GetFilesInDir(localDir, &entries);
for (const auto &entry : entries) {
// TODO: Support browsing into subdirs. How are folders marked?
if (entry.isDirectory || !RemoteISOFileSupported(entry.name)) {
if (!entry.isDirectory && !RemoteISOFileSupported(entry.name)) {
continue;
}
std::string encoded = ServerUriEncode(entry.name);
std::string name = entry.name;
if (entry.isDirectory) {
name.push_back('/');
}
std::string encoded = ServerUriEncode(name);
request.Out()->Printf("%s\n", encoded.c_str());
}
break;
Expand Down Expand Up @@ -325,12 +346,20 @@ static void RedirectToDebugger(const http::ServerRequest &request) {
}

static void HandleFallback(const http::ServerRequest &request) {
SetCurrentThreadName("HandleFallback");

AndroidJNIThreadContext jniContext;

if (serverFlags & (int)WebServerFlags::DISCS) {
Path filename = LocalFromRemotePath(request.resource());
if (!filename.empty()) {
DiscHandler(request, filename);
std::string resource = request.resource();
Path localPath = LocalFromRemotePath(resource);
INFO_LOG(LOADER, "Serving %s from %s", resource.c_str(), localPath.c_str());
if (!localPath.empty()) {
if (File::IsDirectory(localPath)) {
HandleListing(request);
} else {
DiscHandler(request, localPath);
}
return;
}
}
Expand All @@ -351,6 +380,8 @@ static void HandleFallback(const http::ServerRequest &request) {
}

static void ForwardDebuggerRequest(const http::ServerRequest &request) {
SetCurrentThreadName("ForwardDebuggerRequest");

AndroidJNIThreadContext jniContext;

if (serverFlags & (int)WebServerFlags::DEBUGGER) {
Expand Down

0 comments on commit a945682

Please sign in to comment.