1370b324cSopenharmony_ci// ExtractingFilePath.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../Common/Wildcard.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "../../../Windows/FileName.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ci#include "ExtractingFilePath.h"
10370b324cSopenharmony_ci
11370b324cSopenharmony_ciextern
12370b324cSopenharmony_cibool g_PathTrailReplaceMode;
13370b324cSopenharmony_cibool g_PathTrailReplaceMode =
14370b324cSopenharmony_ci    #ifdef _WIN32
15370b324cSopenharmony_ci      true
16370b324cSopenharmony_ci    #else
17370b324cSopenharmony_ci      false
18370b324cSopenharmony_ci    #endif
19370b324cSopenharmony_ci    ;
20370b324cSopenharmony_ci
21370b324cSopenharmony_ci
22370b324cSopenharmony_ci#ifdef _WIN32
23370b324cSopenharmony_cistatic void ReplaceIncorrectChars(UString &s)
24370b324cSopenharmony_ci{
25370b324cSopenharmony_ci  {
26370b324cSopenharmony_ci    for (unsigned i = 0; i < s.Len(); i++)
27370b324cSopenharmony_ci    {
28370b324cSopenharmony_ci      wchar_t c = s[i];
29370b324cSopenharmony_ci      if (
30370b324cSopenharmony_ci          #ifdef _WIN32
31370b324cSopenharmony_ci          c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
32370b324cSopenharmony_ci          || c == '/'
33370b324cSopenharmony_ci          // || c == 0x202E // RLO
34370b324cSopenharmony_ci          ||
35370b324cSopenharmony_ci          #endif
36370b324cSopenharmony_ci          c == WCHAR_PATH_SEPARATOR)
37370b324cSopenharmony_ci      {
38370b324cSopenharmony_ci       #if WCHAR_PATH_SEPARATOR != L'/'
39370b324cSopenharmony_ci        // 22.00 : WSL replacement for backslash
40370b324cSopenharmony_ci        if (c == WCHAR_PATH_SEPARATOR)
41370b324cSopenharmony_ci          c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT;
42370b324cSopenharmony_ci        else
43370b324cSopenharmony_ci       #endif
44370b324cSopenharmony_ci          c = '_';
45370b324cSopenharmony_ci        s.ReplaceOneCharAtPos(i,
46370b324cSopenharmony_ci          c
47370b324cSopenharmony_ci          // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters
48370b324cSopenharmony_ci          );
49370b324cSopenharmony_ci      }
50370b324cSopenharmony_ci    }
51370b324cSopenharmony_ci  }
52370b324cSopenharmony_ci
53370b324cSopenharmony_ci  if (g_PathTrailReplaceMode)
54370b324cSopenharmony_ci  {
55370b324cSopenharmony_ci    /*
56370b324cSopenharmony_ci    // if (g_PathTrailReplaceMode == 1)
57370b324cSopenharmony_ci    {
58370b324cSopenharmony_ci      if (!s.IsEmpty())
59370b324cSopenharmony_ci      {
60370b324cSopenharmony_ci        wchar_t c = s.Back();
61370b324cSopenharmony_ci        if (c == '.' || c == ' ')
62370b324cSopenharmony_ci        {
63370b324cSopenharmony_ci          // s += (wchar_t)(0x9c); // STRING TERMINATOR
64370b324cSopenharmony_ci          s += (wchar_t)'_';
65370b324cSopenharmony_ci        }
66370b324cSopenharmony_ci      }
67370b324cSopenharmony_ci    }
68370b324cSopenharmony_ci    else
69370b324cSopenharmony_ci    */
70370b324cSopenharmony_ci    {
71370b324cSopenharmony_ci      unsigned i;
72370b324cSopenharmony_ci      for (i = s.Len(); i != 0;)
73370b324cSopenharmony_ci      {
74370b324cSopenharmony_ci        wchar_t c = s[i - 1];
75370b324cSopenharmony_ci        if (c != '.' && c != ' ')
76370b324cSopenharmony_ci          break;
77370b324cSopenharmony_ci        i--;
78370b324cSopenharmony_ci        s.ReplaceOneCharAtPos(i, '_');
79370b324cSopenharmony_ci        // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
80370b324cSopenharmony_ci      }
81370b324cSopenharmony_ci      /*
82370b324cSopenharmony_ci      if (g_PathTrailReplaceMode > 1 && i != s.Len())
83370b324cSopenharmony_ci      {
84370b324cSopenharmony_ci        s.DeleteFrom(i);
85370b324cSopenharmony_ci      }
86370b324cSopenharmony_ci      */
87370b324cSopenharmony_ci    }
88370b324cSopenharmony_ci  }
89370b324cSopenharmony_ci}
90370b324cSopenharmony_ci#endif
91370b324cSopenharmony_ci
92370b324cSopenharmony_ci/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.
93370b324cSopenharmony_ci   But colon in postfix ":$DATA" is allowed.
94370b324cSopenharmony_ci   WIN32 functions don't allow empty alt stream name "name:" */
95370b324cSopenharmony_ci
96370b324cSopenharmony_civoid Correct_AltStream_Name(UString &s)
97370b324cSopenharmony_ci{
98370b324cSopenharmony_ci  unsigned len = s.Len();
99370b324cSopenharmony_ci  const unsigned kPostfixSize = 6;
100370b324cSopenharmony_ci  if (s.Len() >= kPostfixSize
101370b324cSopenharmony_ci      && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))
102370b324cSopenharmony_ci    len -= kPostfixSize;
103370b324cSopenharmony_ci  for (unsigned i = 0; i < len; i++)
104370b324cSopenharmony_ci  {
105370b324cSopenharmony_ci    wchar_t c = s[i];
106370b324cSopenharmony_ci    if (c == ':' || c == '\\' || c == '/'
107370b324cSopenharmony_ci        || c == 0x202E // RLO
108370b324cSopenharmony_ci        )
109370b324cSopenharmony_ci      s.ReplaceOneCharAtPos(i, '_');
110370b324cSopenharmony_ci  }
111370b324cSopenharmony_ci  if (s.IsEmpty())
112370b324cSopenharmony_ci    s = '_';
113370b324cSopenharmony_ci}
114370b324cSopenharmony_ci
115370b324cSopenharmony_ci#ifdef _WIN32
116370b324cSopenharmony_ci
117370b324cSopenharmony_cistatic const unsigned g_ReservedWithNum_Index = 4;
118370b324cSopenharmony_ci
119370b324cSopenharmony_cistatic const char * const g_ReservedNames[] =
120370b324cSopenharmony_ci{
121370b324cSopenharmony_ci  "CON", "PRN", "AUX", "NUL",
122370b324cSopenharmony_ci  "COM", "LPT"
123370b324cSopenharmony_ci};
124370b324cSopenharmony_ci
125370b324cSopenharmony_cistatic bool IsSupportedName(const UString &name)
126370b324cSopenharmony_ci{
127370b324cSopenharmony_ci  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ReservedNames); i++)
128370b324cSopenharmony_ci  {
129370b324cSopenharmony_ci    const char *reservedName = g_ReservedNames[i];
130370b324cSopenharmony_ci    unsigned len = MyStringLen(reservedName);
131370b324cSopenharmony_ci    if (name.Len() < len)
132370b324cSopenharmony_ci      continue;
133370b324cSopenharmony_ci    if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
134370b324cSopenharmony_ci      continue;
135370b324cSopenharmony_ci    if (i >= g_ReservedWithNum_Index)
136370b324cSopenharmony_ci    {
137370b324cSopenharmony_ci      wchar_t c = name[len];
138370b324cSopenharmony_ci      if (c < L'0' || c > L'9')
139370b324cSopenharmony_ci        continue;
140370b324cSopenharmony_ci      len++;
141370b324cSopenharmony_ci    }
142370b324cSopenharmony_ci    for (;;)
143370b324cSopenharmony_ci    {
144370b324cSopenharmony_ci      wchar_t c = name[len++];
145370b324cSopenharmony_ci      if (c == 0 || c == '.')
146370b324cSopenharmony_ci        return false;
147370b324cSopenharmony_ci      if (c != ' ')
148370b324cSopenharmony_ci        break;
149370b324cSopenharmony_ci    }
150370b324cSopenharmony_ci  }
151370b324cSopenharmony_ci  return true;
152370b324cSopenharmony_ci}
153370b324cSopenharmony_ci
154370b324cSopenharmony_cistatic void CorrectUnsupportedName(UString &name)
155370b324cSopenharmony_ci{
156370b324cSopenharmony_ci  if (!IsSupportedName(name))
157370b324cSopenharmony_ci    name.InsertAtFront(L'_');
158370b324cSopenharmony_ci}
159370b324cSopenharmony_ci
160370b324cSopenharmony_ci#endif
161370b324cSopenharmony_ci
162370b324cSopenharmony_cistatic void Correct_PathPart(UString &s)
163370b324cSopenharmony_ci{
164370b324cSopenharmony_ci  // "." and ".."
165370b324cSopenharmony_ci  if (s.IsEmpty())
166370b324cSopenharmony_ci    return;
167370b324cSopenharmony_ci
168370b324cSopenharmony_ci  if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
169370b324cSopenharmony_ci    s.Empty();
170370b324cSopenharmony_ci  #ifdef _WIN32
171370b324cSopenharmony_ci  else
172370b324cSopenharmony_ci    ReplaceIncorrectChars(s);
173370b324cSopenharmony_ci  #endif
174370b324cSopenharmony_ci}
175370b324cSopenharmony_ci
176370b324cSopenharmony_ci// static const char * const k_EmptyReplaceName = "[]";
177370b324cSopenharmony_cistatic const char k_EmptyReplaceName = '_';
178370b324cSopenharmony_ci
179370b324cSopenharmony_ciUString Get_Correct_FsFile_Name(const UString &name)
180370b324cSopenharmony_ci{
181370b324cSopenharmony_ci  UString res = name;
182370b324cSopenharmony_ci  Correct_PathPart(res);
183370b324cSopenharmony_ci
184370b324cSopenharmony_ci  #ifdef _WIN32
185370b324cSopenharmony_ci  CorrectUnsupportedName(res);
186370b324cSopenharmony_ci  #endif
187370b324cSopenharmony_ci
188370b324cSopenharmony_ci  if (res.IsEmpty())
189370b324cSopenharmony_ci    res = k_EmptyReplaceName;
190370b324cSopenharmony_ci  return res;
191370b324cSopenharmony_ci}
192370b324cSopenharmony_ci
193370b324cSopenharmony_ci
194370b324cSopenharmony_civoid Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
195370b324cSopenharmony_ci{
196370b324cSopenharmony_ci  unsigned i = 0;
197370b324cSopenharmony_ci
198370b324cSopenharmony_ci  if (absIsAllowed)
199370b324cSopenharmony_ci  {
200370b324cSopenharmony_ci    #if defined(_WIN32) && !defined(UNDER_CE)
201370b324cSopenharmony_ci    bool isDrive = false;
202370b324cSopenharmony_ci    #endif
203370b324cSopenharmony_ci
204370b324cSopenharmony_ci    if (parts[0].IsEmpty())
205370b324cSopenharmony_ci    {
206370b324cSopenharmony_ci      i = 1;
207370b324cSopenharmony_ci      #if defined(_WIN32) && !defined(UNDER_CE)
208370b324cSopenharmony_ci      if (parts.Size() > 1 && parts[1].IsEmpty())
209370b324cSopenharmony_ci      {
210370b324cSopenharmony_ci        i = 2;
211370b324cSopenharmony_ci        if (parts.Size() > 2 && parts[2] == L"?")
212370b324cSopenharmony_ci        {
213370b324cSopenharmony_ci          i = 3;
214370b324cSopenharmony_ci          if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
215370b324cSopenharmony_ci          {
216370b324cSopenharmony_ci            isDrive = true;
217370b324cSopenharmony_ci            i = 4;
218370b324cSopenharmony_ci          }
219370b324cSopenharmony_ci        }
220370b324cSopenharmony_ci      }
221370b324cSopenharmony_ci      #endif
222370b324cSopenharmony_ci    }
223370b324cSopenharmony_ci    #if defined(_WIN32) && !defined(UNDER_CE)
224370b324cSopenharmony_ci    else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))
225370b324cSopenharmony_ci    {
226370b324cSopenharmony_ci      isDrive = true;
227370b324cSopenharmony_ci      i = 1;
228370b324cSopenharmony_ci    }
229370b324cSopenharmony_ci
230370b324cSopenharmony_ci    if (isDrive)
231370b324cSopenharmony_ci    {
232370b324cSopenharmony_ci      // we convert "c:name" to "c:\name", if absIsAllowed path.
233370b324cSopenharmony_ci      UString &ds = parts[i - 1];
234370b324cSopenharmony_ci      if (ds.Len() > 2)
235370b324cSopenharmony_ci      {
236370b324cSopenharmony_ci        parts.Insert(i, ds.Ptr(2));
237370b324cSopenharmony_ci        ds.DeleteFrom(2);
238370b324cSopenharmony_ci      }
239370b324cSopenharmony_ci    }
240370b324cSopenharmony_ci    #endif
241370b324cSopenharmony_ci  }
242370b324cSopenharmony_ci
243370b324cSopenharmony_ci  if (i != 0)
244370b324cSopenharmony_ci    keepAndReplaceEmptyPrefixes = false;
245370b324cSopenharmony_ci
246370b324cSopenharmony_ci  for (; i < parts.Size();)
247370b324cSopenharmony_ci  {
248370b324cSopenharmony_ci    UString &s = parts[i];
249370b324cSopenharmony_ci
250370b324cSopenharmony_ci    Correct_PathPart(s);
251370b324cSopenharmony_ci
252370b324cSopenharmony_ci    if (s.IsEmpty())
253370b324cSopenharmony_ci    {
254370b324cSopenharmony_ci      if (!keepAndReplaceEmptyPrefixes)
255370b324cSopenharmony_ci        if (isDir || i != parts.Size() - 1)
256370b324cSopenharmony_ci        {
257370b324cSopenharmony_ci          parts.Delete(i);
258370b324cSopenharmony_ci          continue;
259370b324cSopenharmony_ci        }
260370b324cSopenharmony_ci      s = k_EmptyReplaceName;
261370b324cSopenharmony_ci    }
262370b324cSopenharmony_ci    else
263370b324cSopenharmony_ci    {
264370b324cSopenharmony_ci      keepAndReplaceEmptyPrefixes = false;
265370b324cSopenharmony_ci      #ifdef _WIN32
266370b324cSopenharmony_ci      CorrectUnsupportedName(s);
267370b324cSopenharmony_ci      #endif
268370b324cSopenharmony_ci    }
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci    i++;
271370b324cSopenharmony_ci  }
272370b324cSopenharmony_ci
273370b324cSopenharmony_ci  if (!isDir)
274370b324cSopenharmony_ci  {
275370b324cSopenharmony_ci    if (parts.IsEmpty())
276370b324cSopenharmony_ci      parts.Add((UString)k_EmptyReplaceName);
277370b324cSopenharmony_ci    else
278370b324cSopenharmony_ci    {
279370b324cSopenharmony_ci      UString &s = parts.Back();
280370b324cSopenharmony_ci      if (s.IsEmpty())
281370b324cSopenharmony_ci        s = k_EmptyReplaceName;
282370b324cSopenharmony_ci    }
283370b324cSopenharmony_ci  }
284370b324cSopenharmony_ci}
285370b324cSopenharmony_ci
286370b324cSopenharmony_ciUString MakePathFromParts(const UStringVector &parts)
287370b324cSopenharmony_ci{
288370b324cSopenharmony_ci  UString s;
289370b324cSopenharmony_ci  FOR_VECTOR (i, parts)
290370b324cSopenharmony_ci  {
291370b324cSopenharmony_ci    if (i != 0)
292370b324cSopenharmony_ci      s.Add_PathSepar();
293370b324cSopenharmony_ci    s += parts[i];
294370b324cSopenharmony_ci  }
295370b324cSopenharmony_ci  return s;
296370b324cSopenharmony_ci}
297