// ExtractingFilePath.cpp | |
#include "StdAfx.h" | |
#include "../../../Common/Wildcard.h" | |
#include "../../../Windows/FileName.h" | |
#include "ExtractingFilePath.h" | |
static UString ReplaceIncorrectChars(const UString &s, bool repaceColon) | |
{ | |
#ifdef _WIN32 | |
UString res; | |
bool beforeColon = true; | |
{ | |
for (unsigned i = 0; i < s.Len(); i++) | |
{ | |
wchar_t c = s[i]; | |
if (beforeColon) | |
if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"') | |
c = '_'; | |
if (c == ':') | |
{ | |
if (repaceColon) | |
c = '_'; | |
else | |
beforeColon = false; | |
} | |
res += c; | |
} | |
} | |
if (beforeColon) | |
{ | |
for (int i = res.Len() - 1; i >= 0; i--) | |
{ | |
wchar_t c = res[i]; | |
if (c != '.' && c != ' ') | |
break; | |
res.ReplaceOneCharAtPos(i, '_'); | |
} | |
} | |
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, unsigned len) | |
{ | |
int dotPos = name.Find(L'.'); | |
if (dotPos < 0) | |
dotPos = name.Len(); | |
UString s = name.Left(dotPos); | |
s.TrimRight(); | |
return s.Len() != len; | |
} | |
static bool CheckNameNum(const UString &name, const wchar_t *reservedName) | |
{ | |
unsigned len = MyStringLen(reservedName); | |
if (name.Len() <= len) | |
return true; | |
if (MyStringCompareNoCase_N(name, reservedName, len) != 0) | |
return true; | |
wchar_t c = name[len]; | |
if (c < L'0' || c > L'9') | |
return true; | |
return CheckTail(name, len + 1); | |
} | |
static bool IsSupportedName(const UString &name) | |
{ | |
for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++) | |
{ | |
const wchar_t *reservedName = g_ReservedNames[i]; | |
unsigned len = MyStringLen(reservedName); | |
if (name.Len() < len) | |
continue; | |
if (MyStringCompareNoCase_N(name, reservedName, len) != 0) | |
continue; | |
if (!CheckTail(name, len)) | |
return false; | |
} | |
if (!CheckNameNum(name, L"COM")) | |
return false; | |
return CheckNameNum(name, L"LPT"); | |
} | |
#endif | |
static UString GetCorrectFileName(const UString &path, bool repaceColon) | |
{ | |
if (path == L".." || path == L".") | |
return UString(); | |
return ReplaceIncorrectChars(path, repaceColon); | |
} | |
void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon) | |
{ | |
for (unsigned i = 0; i < pathParts.Size();) | |
{ | |
UString &s = pathParts[i]; | |
#ifdef _WIN32 | |
bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1); | |
if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s)) | |
{ | |
UString s2 = s[0]; | |
s2 += L'_'; | |
s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon); | |
s = s2; | |
} | |
else | |
s = GetCorrectFileName(s, needReplaceColon); | |
#endif | |
if (s.IsEmpty()) | |
pathParts.Delete(i); | |
else | |
{ | |
#ifdef _WIN32 | |
if (!IsSupportedName(s)) | |
s = (UString)L"_" + s; | |
#endif | |
i++; | |
} | |
} | |
} | |
UString MakePathNameFromParts(const UStringVector &parts) | |
{ | |
UString result; | |
FOR_VECTOR (i, parts) | |
{ | |
if (i != 0) | |
result += WCHAR_PATH_SEPARATOR; | |
result += parts[i]; | |
} | |
return result; | |
} | |
static const wchar_t *k_EmptyReplaceName = L"[]"; | |
void Correct_IfEmptyLastPart(UStringVector &parts) | |
{ | |
if (parts.IsEmpty()) | |
parts.Add(k_EmptyReplaceName); | |
else | |
{ | |
UString &s = parts.Back(); | |
if (s.IsEmpty()) | |
s = k_EmptyReplaceName; | |
} | |
} | |
UString GetCorrectFsPath(const UString &path) | |
{ | |
UString res = GetCorrectFileName(path, true); | |
#ifdef _WIN32 | |
if (!IsSupportedName(res)) | |
res = (UString)L"_" + res; | |
#endif | |
if (res.IsEmpty()) | |
res = k_EmptyReplaceName; | |
return res; | |
} | |
UString GetCorrectFullFsPath(const UString &path) | |
{ | |
UStringVector parts; | |
SplitPathToParts(path, parts); | |
FOR_VECTOR (i, parts) | |
{ | |
UString &s = parts[i]; | |
#ifdef _WIN32 | |
while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' ')) | |
s.DeleteBack(); | |
if (!IsSupportedName(s)) | |
s.InsertAtFront(L'_'); | |
#endif | |
} | |
return MakePathNameFromParts(parts); | |
} |