Source code

Revision control

Copy as Markdown

Other Tools

// ExtractingFilePath.cpp↩
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileName.h"
#include "ExtractingFilePath.h"
bool g_PathTrailReplaceMode =↩
#ifdef _WIN32↩
true
#else
false
#endif
;↩
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, '_');↩
}↩
}↩
if (g_PathTrailReplaceMode)↩
{↩
/*↩
// if (g_PathTrailReplaceMode == 1)↩
{↩
if (!s.IsEmpty())↩
{↩
wchar_t c = s.Back();↩
if (c == '.' || c == ' ')↩
{↩
// s += (wchar_t)(0x9c); // STRING TERMINATOR↩
s += (wchar_t)'_';↩
}↩
}↩
}↩
else↩
*/
{↩
unsigned i;↩
for (i = s.Len(); i != 0;)↩
{↩
wchar_t c = s[i - 1];↩
if (c != '.' && c != ' ')↩
break;↩
i--;↩
s.ReplaceOneCharAtPos(i, '_');↩
// s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));↩
}↩
/*↩
if (g_PathTrailReplaceMode > 1 && i != s.Len())↩
{↩
s.DeleteFrom(i);↩
}↩
*/
}↩
}↩
}↩
#ifdef _WIN32↩
/* 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)↩
{↩
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 = '_';↩
}↩
static const unsigned g_ReservedWithNum_Index = 4;↩
static const char * const g_ReservedNames[] =↩
{↩
"CON", "PRN", "AUX", "NUL",↩
"COM", "LPT"
};↩
static bool IsSupportedName(const UString &name)↩
{↩
for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)↩
{↩
const char *reservedName = g_ReservedNames[i];↩
unsigned len = MyStringLen(reservedName);↩
if (name.Len() < len)↩
continue;↩
if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))↩
continue;↩
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;↩
}↩
}↩
return true;↩
}↩
static void CorrectUnsupportedName(UString &name)↩
{↩
if (!IsSupportedName(name))↩
name.InsertAtFront(L'_');↩
}↩
#endif
static void Correct_PathPart(UString &s)↩
{↩
// "." and ".."↩
if (s.IsEmpty())↩
return;↩
if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))↩
s.Empty();↩
#ifdef _WIN32↩
else
ReplaceIncorrectChars(s);↩
#endif
}↩
// static const char * const k_EmptyReplaceName = "[]";↩
static const char k_EmptyReplaceName = '_';↩
UString Get_Correct_FsFile_Name(const UString &name)↩
{↩
UString res = name;↩
Correct_PathPart(res);↩
#ifdef _WIN32↩
CorrectUnsupportedName(res);↩
#endif
if (res.IsEmpty())↩
res = k_EmptyReplaceName;↩
return res;↩
}↩
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)↩
{↩
unsigned i = 0;↩
if (absIsAllowed)↩
{↩
#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.↩
UString &ds = parts[i - 1];↩
if (ds.Len() > 2)↩
{↩
parts.Insert(i, ds.Ptr(2));↩
ds.DeleteFrom(2);↩
}↩
}↩
#endif
}↩
if (i != 0)↩
keepAndReplaceEmptyPrefixes = false;↩
for (; i < parts.Size();)↩
{↩
UString &s = parts[i];↩
Correct_PathPart(s);↩
if (s.IsEmpty())↩
{↩
if (!keepAndReplaceEmptyPrefixes)↩
if (isDir || i != parts.Size() - 1)↩
{↩
parts.Delete(i);↩
continue;↩
}↩
s = k_EmptyReplaceName;↩
}↩
else
{↩
keepAndReplaceEmptyPrefixes = false;↩
#ifdef _WIN32↩
CorrectUnsupportedName(s);↩
#endif
}↩
i++;↩
}↩
if (!isDir)↩
{↩
if (parts.IsEmpty())↩
parts.Add((UString)k_EmptyReplaceName);↩
else
{↩
UString &s = parts.Back();↩
if (s.IsEmpty())↩
s = k_EmptyReplaceName;↩
}↩
}↩
}↩
UString MakePathFromParts(const UStringVector &parts)↩
{↩
UString s;↩
FOR_VECTOR (i, parts)↩
{↩
if (i != 0)↩
s.Add_PathSepar();↩
s += parts[i];↩
}↩
return s;↩
}↩