Browse Source

Normalize slashes in paths unless they are direct user input (XDG_DATA_HOME/APPDATA, specifically)

Bart van Strien 11 years ago
parent
commit
59ab602111
1 changed files with 26 additions and 15 deletions
  1. 26 15
      src/modules/filesystem/physfs/Filesystem.cpp

+ 26 - 15
src/modules/filesystem/physfs/Filesystem.cpp

@@ -21,6 +21,7 @@
 #include "common/config.h"
 
 #include <iostream>
+#include <sstream>
 
 #include "common/utf8.h"
 #include "common/b64.h"
@@ -47,6 +48,21 @@ namespace
 	{
 		return input.substr(getDriveDelim(input)+1);
 	}
+
+	std::string normalize(const std::string &input)
+	{
+		std::stringstream out;
+		bool seenSep = false, isSep = false;
+		for (size_t i = 0; i < input.size(); ++i)
+		{
+			isSep = (input[i] == LOVE_PATH_SEPARATOR[0]);
+			if (!isSep || !seenSep)
+				out << input[i];
+			seenSep = isSep;
+		}
+
+		return out.str();
+	}
 }
 
 namespace love
@@ -116,6 +132,8 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
 	else
 		save_path_full += save_path_relative;
 
+	save_path_full = normalize(save_path_full);
+
 	// We now have something like:
 	// save_identity: game
 	// save_path_relative: ./LOVE/game
@@ -354,40 +372,33 @@ const char *Filesystem::getWorkingDirectory()
 
 std::string Filesystem::getUserDirectory()
 {
-	return std::string(PHYSFS_getUserDir());
+	static std::string userDir = normalize(PHYSFS_getUserDir());
+	return userDir;
 }
 
 std::string Filesystem::getAppdataDirectory()
 {
-#ifdef LOVE_WINDOWS
 	if (appdata.empty())
 	{
+#ifdef LOVE_WINDOWS
 		wchar_t *w_appdata = _wgetenv(L"APPDATA");
 		appdata = to_utf8(w_appdata);
 		replace_char(appdata, '\\', '/');
-	}
-	return appdata;
 #elif defined(LOVE_MACOSX)
-	if (appdata.empty())
-	{
 		std::string udir = getUserDirectory();
 		udir.append("/Library/Application Support");
-		appdata = udir;
-	}
-	return appdata;
+		appdata = normalize(udir);
 #elif defined(LOVE_LINUX)
-	if (appdata.empty())
-	{
 		char *xdgdatahome = getenv("XDG_DATA_HOME");
 		if (!xdgdatahome)
-			appdata = std::string(getUserDirectory()) + "/.local/share/";
+			appdata = normalize(std::string(getUserDirectory()) + "/.local/share/");
 		else
 			appdata = xdgdatahome;
-	}
-	return appdata;
 #else
-	return getUserDirectory();
+		appdata = getUserDirectory();
 #endif
+	}
+	return appdata;
 }