Browse Source

Fixed opening workspace paths containing '/../' or '/./'

Brian Fiete 5 năm trước cách đây
mục cha
commit
c2ee401812

+ 43 - 9
BeefySysLib/platform/win/Platform.cpp

@@ -3150,18 +3150,52 @@ BFP_EXPORT void BFP_CALLTYPE BfpFile_GetActualPath(const char* inPathC, char* ou
 {
 	String inPath = inPathC;
 	String outPath;
+	
+	// Check for '/../' backtracking - handle those first
+	{
+		int i = 0;
+		int32 lastComponentStart = -1;		
+		String subName;
+		
+		while (i < inPath.mLength)
+		{
+			// skip until path separator
+			while ((i < inPath.mLength) && (inPath[i] != DIR_SEP_CHAR) && (inPath[i] != DIR_SEP_CHAR_ALT))
+				++i;
+			
+			if (lastComponentStart != -1)
+			{
+				if ((i - lastComponentStart == 2) && (inPath[lastComponentStart] == '.') && (inPath[lastComponentStart + 1] == '.'))
+				{
+					// Backtrack
+					while ((lastComponentStart > 0) && 
+						((inPath[lastComponentStart - 1] == DIR_SEP_CHAR) || (inPath[lastComponentStart - 1] == DIR_SEP_CHAR_ALT)))
+						lastComponentStart--;
+					while ((lastComponentStart > 0) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR) && (inPath[lastComponentStart - 1] != DIR_SEP_CHAR_ALT))
+						lastComponentStart--;
+					inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
+					i = lastComponentStart;
+					continue;					
+				}
+				else if ((i - lastComponentStart == 1) && (inPath[lastComponentStart] == '.'))
+				{					
+					inPath.Remove(lastComponentStart, i - lastComponentStart + 1);
+					i = lastComponentStart;
+					continue;
+				}
+			}
 
-	// This is quite involved, but the meat is SHGetFileInfo
-	//const wchar8_t kSeparator = L'\\';
-	// copy input string because we'll be temporary modifying it in place
-	//size_t length = wcslen(path);
-	//wchar8_t buffer[MAX_PATH];
-	//memcpy( buffer, path, (length+1) * sizeof(path[0]) );
-
-	int32 i = 0;
+			++i;
+			// Ignore multiple slashes in a row
+			while ((i < inPath.mLength) && ((inPath[i] == DIR_SEP_CHAR) || (inPath[i] == DIR_SEP_CHAR_ALT)))
+				++i;
 
-	//UTF16String result;
+			lastComponentStart = i;			
+		}
+	}
 
+	int32 i = 0;
+	
 	// for network paths (\\server\share\RestOfPath), getting the display
 	// name mangles it into unusable form (e.g. "\\server\share" turns
 	// into "share on server (server)"). So detect this case and just skip

+ 1 - 0
IDE/src/FileEditData.bf

@@ -7,6 +7,7 @@ using System.Security.Cryptography;
 
 namespace IDE
 {
+	[AllowDuplicates]
 	public enum LineEndingKind
 	{
 		Lf,   // \n

+ 3 - 0
IDE/src/IDEApp.bf

@@ -804,6 +804,9 @@ namespace IDE
 #if !CLI
 			if (mDeferredOpenFileName != null)
 			{
+				String prevFilePath = scope .(mDeferredOpenFileName);
+				mDeferredOpenFileName.Clear();
+				Path.GetActualPathName(prevFilePath, mDeferredOpenFileName);
 				OpenWorkspace(mDeferredOpenFileName);
 				DeleteAndNullify!(mDeferredOpenFileName);
 				return;

+ 1 - 0
IDE/src/ui/MemoryPanel.bf

@@ -36,6 +36,7 @@ namespace IDE.ui
 
     public class MemoryRepListView : DarkListView
     {
+		[AllowDuplicates]
         public enum RepType
         {
             // integer types (dual signed/unsigned reps)

+ 1 - 0
IDE/src/util/Curl.bf

@@ -14,6 +14,7 @@ namespace CURL
 		const int32 cOptionFunction = 20000;
 		const int32 cOptionOffT = 30000;
 
+		[AllowDuplicates]
 		public enum Option
 		{
 			/* This is the FILE * or void * the regular output should be written to. */

+ 1 - 1
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -2992,7 +2992,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 					}
 					else if ((typeInstance->mCustomAttributes == NULL) || (typeInstance->mCustomAttributes->Get(mCompiler->mAllowDuplicatesAttributeTypeDef) == NULL))
 					{
-						auto error = Warn(0, StrFormat("Enum value '%lld' for field '%s' is not unique", foreignConst->mInt64, fieldDef->mName.c_str()), fieldDef->GetRefNode(), true);
+						auto error = Warn(0, StrFormat("Enum value '%lld' for field '%s' is not unique. Considering adding [AllowDuplicates] to the type declaration.", foreignConst->mInt64, fieldDef->mName.c_str()), fieldDef->GetRefNode(), true);
 						if (error != NULL)
 							mCompiler->mPassInstance->MoreInfo(StrFormat("This value was previously used for field '%s'", (*fieldDefPtr)->mName.c_str()), (*fieldDefPtr)->GetRefNode());
 					}