// 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);
}