Permalink
Browse files

UI: Resolve symlinks when adding things to recent.

See #11131.  This also normalizes paths, captialization, etc. as
necessary.
  • Loading branch information...
unknownbrackets committed Aug 12, 2018
1 parent 1fdb1f7 commit 048afb6d24199d7dc9c241cb8a10aa3251985f68
Showing with 52 additions and 38 deletions.
  1. +22 −0 Common/FileUtil.cpp
  2. +3 −0 Common/FileUtil.h
  3. +19 −15 Core/Config.cpp
  4. +1 −0 Core/Config.h
  5. +1 −1 Core/FileSystems/VirtualDiscFileSystem.cpp
  6. +1 −4 UI/GameInfoCache.cpp
  7. +5 −18 UI/GameScreen.cpp
@@ -100,6 +100,28 @@ bool OpenCPPFile(std::fstream & stream, const std::string &filename, std::ios::o
return stream.is_open();
}
std::string ResolvePath(const std::string &path) {
#ifdef _WIN32
HANDLE hFile = CreateFile(ConvertUTF8ToWString(path).c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
return path;
wchar_t buf[1024] = {0};
int result = GetFinalPathNameByHandle(hFile, buf, (int)ARRAY_SIZE(buf) - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
if (result >= ARRAY_SIZE(buf))
return path;
// Undo the \\?\C:\ syntax that's normally returned.
if (buf[0] == '\\' && buf[1] == '\\' && buf[2] == '?' && buf[3] == '\\' && isalpha(buf[4]) && buf[5] == ':')
return ConvertWStringToUTF8(buf).substr(4);
return ConvertWStringToUTF8(buf);
#else
char buf[PATH_MAX + 1];
if (realpath(path.c_str(), buf) == nullptr)
return path;
return buf;
#endif
}
// Remove any ending forward slashes from directory paths
// Modifies argument.
@@ -58,6 +58,9 @@ struct FileDetails {
FILE *OpenCFile(const std::string &filename, const char *mode);
bool OpenCPPFile(std::fstream & stream, const std::string &filename, std::ios::openmode mode);
// Resolves symlinks and similar.
std::string ResolvePath(const std::string &path);
// Returns true if file filename exists
bool Exists(const std::string &filename);
@@ -1209,30 +1209,34 @@ void Config::AddRecent(const std::string &file) {
if (iMaxRecent <= 0)
return;
#ifdef _WIN32
std::string filename = ReplaceAll(file, "\\", "/");
#else
std::string filename = file;
#endif
const std::string filename = File::ResolvePath(file);
for (auto str = recentIsos.begin(); str != recentIsos.end(); ++str) {
#ifdef _WIN32
if (!strcmpIgnore((*str).c_str(), filename.c_str(), "\\", "/")) {
#else
if (!strcmp((*str).c_str(), filename.c_str())) {
#endif
const std::string recent = File::ResolvePath(*str);
if (filename == recent) {
recentIsos.erase(str);
recentIsos.insert(recentIsos.begin(), filename);
if ((int)recentIsos.size() > iMaxRecent)
recentIsos.resize(iMaxRecent);
return;
// We'll add it back below.
}
}
recentIsos.insert(recentIsos.begin(), filename);
if ((int)recentIsos.size() > iMaxRecent)
recentIsos.resize(iMaxRecent);
}
void Config::RemoveRecent(const std::string &file) {
// Don't bother with this if the user disabled recents (it's -1).
if (iMaxRecent <= 0)
return;
const std::string filename = File::ResolvePath(file);
for (auto str = recentIsos.begin(); str != recentIsos.end(); ++str) {
const std::string recent = File::ResolvePath(*str);
if (filename == recent) {
recentIsos.erase(str);
}
}
}
void Config::CleanRecent() {
std::vector<std::string> cleanedRecent;
for (size_t i = 0; i < recentIsos.size(); i++) {
@@ -428,6 +428,7 @@ struct Config {
// Utility functions for "recent" management
void AddRecent(const std::string &file);
void RemoveRecent(const std::string &file);
void CleanRecent();
static void DownloadCompletedCallback(http::Download &download);
@@ -44,7 +44,7 @@ VirtualDiscFileSystem::VirtualDiscFileSystem(IHandleAllocator *_hAlloc, std::str
: basePath(_basePath),currentBlockIndex(0) {
#ifdef _WIN32
if (!endsWith(basePath, "\\"))
if (!endsWith(basePath, "\\") && !endsWith(basePath, "/"))
basePath = basePath + "\\";
#else
if (!endsWith(basePath, "/"))
@@ -66,10 +66,7 @@ bool GameInfo::Delete() {
// Just delete the one file (TODO: handle two-disk games as well somehow).
const char *fileToRemove = filePath_.c_str();
File::Delete(fileToRemove);
auto i = std::find(g_Config.recentIsos.begin(), g_Config.recentIsos.end(), fileToRemove);
if (i != g_Config.recentIsos.end()) {
g_Config.recentIsos.erase(i);
}
g_Config.RemoveRecent(filePath_);
return true;
}
case IdentifiedFileType::PSP_PBP_DIRECTORY:
@@ -354,31 +354,18 @@ bool GameScreen::isRecentGame(const std::string &gamePath) {
if (g_Config.iMaxRecent <= 0)
return false;
const std::string resolved = File::ResolvePath(gamePath);
for (auto it = g_Config.recentIsos.begin(); it != g_Config.recentIsos.end(); ++it) {
#ifdef _WIN32
if (!strcmpIgnore((*it).c_str(), gamePath.c_str(), "\\","/"))
#else
if (!strcmp((*it).c_str(), gamePath.c_str()))
#endif
const std::string recent = File::ResolvePath(*it);
if (resolved == recent)
return true;
}
return false;
}
UI::EventReturn GameScreen::OnRemoveFromRecent(UI::EventParams &e) {
if (g_Config.iMaxRecent <= 0)
return UI::EVENT_DONE;
for (auto it = g_Config.recentIsos.begin(); it != g_Config.recentIsos.end(); ++it) {
#ifdef _WIN32
if (!strcmpIgnore((*it).c_str(), gamePath_.c_str(), "\\","/")) {
#else
if (!strcmp((*it).c_str(), gamePath_.c_str())) {
#endif
g_Config.recentIsos.erase(it);
screenManager()->switchScreen(new MainScreen());
return UI::EVENT_DONE;
}
}
g_Config.RemoveRecent(gamePath_);
screenManager()->switchScreen(new MainScreen());
return UI::EVENT_DONE;
}

0 comments on commit 048afb6

Please sign in to comment.