diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp | 275 |
1 files changed, 185 insertions, 90 deletions
diff --git a/3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 25494d0e642..39e67b7f2ed 100644 --- a/3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/3rdparty/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -2,141 +2,236 @@ #include "StdAfx.h" -#include "../../../../C/Types.h" +#include "../../../Common/Wildcard.h" -#include "Common/Wildcard.h" +#include "../../../Windows/FileName.h" #include "ExtractingFilePath.h" -static UString ReplaceIncorrectChars(const UString &s) +static void ReplaceIncorrectChars(UString &s) { + { + for (unsigned i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if ( + #ifdef _WIN32 + c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"' + || c == '/' + // || c == 0x202E // RLO + || + #endif + c == WCHAR_PATH_SEPARATOR) + s.ReplaceOneCharAtPos(i, '_'); + } + } + #ifdef _WIN32 - UString res; - for (int i = 0; i < s.Length(); i++) { - wchar_t c = s[i]; - if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"') - c = '_'; - res += c; + for (unsigned i = s.Len(); i != 0;) + { + wchar_t c = s[--i]; + if (c != '.' && c != ' ') + break; + s.ReplaceOneCharAtPos(i, '_'); + } } - res.TrimRight(); - while (!res.IsEmpty() && res.Back() == '.') - res.DeleteBack(); - return res; - #else - return s; #endif } #ifdef _WIN32 -static const wchar_t *g_ReservedNames[] = -{ - L"CON", L"PRN", L"AUX", L"NUL" -}; -static bool CheckTail(const UString &name, int len) +/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream. + But colon in postfix ":$DATA" is allowed. + WIN32 functions don't allow empty alt stream name "name:" */ + +void Correct_AltStream_Name(UString &s) { - int dotPos = name.Find(L'.'); - if (dotPos < 0) - dotPos = name.Length(); - UString s = name.Left(dotPos); - s.TrimRight(); - return (s.Length() != len); + unsigned len = s.Len(); + const unsigned kPostfixSize = 6; + if (s.Len() >= kPostfixSize + && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA")) + len -= kPostfixSize; + for (unsigned i = 0; i < len; i++) + { + wchar_t c = s[i]; + if (c == ':' || c == '\\' || c == '/' + || c == 0x202E // RLO + ) + s.ReplaceOneCharAtPos(i, '_'); + } + if (s.IsEmpty()) + s = L'_'; } -static bool CheckNameNum(const UString &name, const wchar_t *reservedName) +static const unsigned g_ReservedWithNum_Index = 4; + +static const char * const g_ReservedNames[] = { - int len = MyStringLen(reservedName); - if (name.Length() <= len) - return true; - if (name.Left(len).CompareNoCase(reservedName) != 0) - return true; - wchar_t c = name[len]; - if (c < L'0' || c > L'9') - return true; - return CheckTail(name, len + 1); -} + "CON", "PRN", "AUX", "NUL", + "COM", "LPT" +}; static bool IsSupportedName(const UString &name) { - for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) { - const wchar_t *reservedName = g_ReservedNames[i]; - int len = MyStringLen(reservedName); - if (name.Length() < len) + const char *reservedName = g_ReservedNames[i]; + unsigned len = MyStringLen(reservedName); + if (name.Len() < len) continue; - if (name.Left(len).CompareNoCase(reservedName) != 0) + if (!name.IsPrefixedBy_Ascii_NoCase(reservedName)) continue; - if (!CheckTail(name, len)) - return false; + if (i >= g_ReservedWithNum_Index) + { + wchar_t c = name[len]; + if (c < L'0' || c > L'9') + continue; + len++; + } + for (;;) + { + wchar_t c = name[len++]; + if (c == 0 || c == '.') + return false; + if (c != ' ') + break; + } } - if (!CheckNameNum(name, L"COM")) - return false; - return CheckNameNum(name, L"LPT"); + return true; } + +static void CorrectUnsupportedName(UString &name) +{ + if (!IsSupportedName(name)) + name.InsertAtFront(L'_'); +} + #endif -static UString GetCorrectFileName(const UString &path) +static void Correct_PathPart(UString &s) +{ + // "." and ".." + if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0)) + s.Empty(); + #ifdef _WIN32 + else + ReplaceIncorrectChars(s); + #endif +} + +// static const wchar_t *k_EmptyReplaceName = L"[]"; +static const wchar_t k_EmptyReplaceName = L'_'; + +UString Get_Correct_FsFile_Name(const UString &name) { - if (path == L".." || path == L".") - return UString(); - return ReplaceIncorrectChars(path); + UString res = name; + Correct_PathPart(res); + + #ifdef _WIN32 + CorrectUnsupportedName(res); + #endif + + if (res.IsEmpty()) + res = k_EmptyReplaceName; + return res; } -void MakeCorrectPath(UStringVector &pathParts) + +void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir) { - for (int i = 0; i < pathParts.Size();) + unsigned i = 0; + + if (absIsAllowed) { - UString &s = pathParts[i]; - s = GetCorrectFileName(s); + #if defined(_WIN32) && !defined(UNDER_CE) + bool isDrive = false; + #endif + if (parts[0].IsEmpty()) + { + i = 1; + #if defined(_WIN32) && !defined(UNDER_CE) + if (parts.Size() > 1 && parts[1].IsEmpty()) + { + i = 2; + if (parts.Size() > 2 && parts[2] == L"?") + { + i = 3; + if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) + { + isDrive = true; + i = 4; + } + } + } + #endif + } + #if defined(_WIN32) && !defined(UNDER_CE) + else if (NWindows::NFile::NName::IsDrivePath2(parts[0])) + { + isDrive = true; + i = 1; + } + + if (isDrive) + { + // we convert "c:name" to "c:\name", if absIsAllowed path. + const UString &ds = parts[i - 1]; + if (ds.Len() != 2) + { + UString s = ds.Ptr(2); + parts.Insert(i, s); + } + } + #endif + } + + for (; i < parts.Size();) + { + UString &s = parts[i]; + + Correct_PathPart(s); + if (s.IsEmpty()) - pathParts.Delete(i); + { + if (isDir || i != parts.Size() - 1) + { + parts.Delete(i); + continue; + } + s = k_EmptyReplaceName; + } else { #ifdef _WIN32 - if (!IsSupportedName(s)) - s = (UString)L"_" + s; + CorrectUnsupportedName(s); #endif - i++; } + + i++; } -} -UString MakePathNameFromParts(const UStringVector &parts) -{ - UString result; - for (int i = 0; i < parts.Size(); i++) + if (!isDir) { - if (i != 0) - result += WCHAR_PATH_SEPARATOR; - result += parts[i]; + if (parts.IsEmpty()) + parts.Add(k_EmptyReplaceName); + else + { + UString &s = parts.Back(); + if (s.IsEmpty()) + s = k_EmptyReplaceName; + } } - return result; } -UString GetCorrectFsPath(const UString &path) -{ - UString res = GetCorrectFileName(path); - #ifdef _WIN32 - if (!IsSupportedName(res)) - res = (UString)L"_" + res; - #endif - return res; -} - -UString GetCorrectFullFsPath(const UString &path) +UString MakePathFromParts(const UStringVector &parts) { - UStringVector parts; - SplitPathToParts(path, parts); - for (int i = 0; i < parts.Size(); i++) + UString s; + FOR_VECTOR (i, parts) { - UString &s = parts[i]; - #ifdef _WIN32 - while (!s.IsEmpty() && s.Back() == '.') - s.DeleteBack(); - if (!IsSupportedName(s)) - s = (UString)L"_" + s; - #endif + if (i != 0) + s.Add_PathSepar(); + s += parts[i]; } - return MakePathNameFromParts(parts); + return s; } |