1// ExtractingFilePath.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/Types.h"
6
7#include "Common/Wildcard.h"
8
9#include "ExtractingFilePath.h"
10
11static UString ReplaceIncorrectChars(const UString &s)
12{
13  #ifdef _WIN32
14  UString res;
15  for (int i = 0; i < s.Length(); i++)
16  {
17    wchar_t c = s[i];
18    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')
19      c = '_';
20    res += c;
21  }
22  res.TrimRight();
23  while (!res.IsEmpty() && res[res.Length() - 1] == '.')
24    res.Delete(res.Length() - 1);
25  return res;
26  #else
27  return s;
28  #endif
29}
30
31#ifdef _WIN32
32static const wchar_t *g_ReservedNames[] =
33{
34  L"CON", L"PRN", L"AUX", L"NUL"
35};
36
37static bool CheckTail(const UString &name, int len)
38{
39  int dotPos = name.Find(L'.');
40  if (dotPos < 0)
41    dotPos = name.Length();
42  UString s = name.Left(dotPos);
43  s.TrimRight();
44  return (s.Length() != len);
45}
46
47static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
48{
49  int len = MyStringLen(reservedName);
50  if (name.Length() <= len)
51    return true;
52  if (name.Left(len).CompareNoCase(reservedName) != 0)
53    return true;
54  wchar_t c = name[len];
55  if (c < L'0' || c > L'9')
56    return true;
57  return CheckTail(name, len + 1);
58}
59
60static bool IsSupportedName(const UString &name)
61{
62  for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++)
63  {
64    const wchar_t *reservedName = g_ReservedNames[i];
65    int len = MyStringLen(reservedName);
66    if (name.Length() < len)
67      continue;
68    if (name.Left(len).CompareNoCase(reservedName) != 0)
69      continue;
70    if (!CheckTail(name, len))
71      return false;
72  }
73  if (!CheckNameNum(name, L"COM"))
74    return false;
75  return CheckNameNum(name, L"LPT");
76}
77#endif
78
79static UString GetCorrectFileName(const UString &path)
80{
81  if (path == L".." || path == L".")
82    return UString();
83  return ReplaceIncorrectChars(path);
84}
85
86void MakeCorrectPath(UStringVector &pathParts)
87{
88  for (int i = 0; i < pathParts.Size();)
89  {
90    UString &s = pathParts[i];
91    s = GetCorrectFileName(s);
92    if (s.IsEmpty())
93      pathParts.Delete(i);
94    else
95    {
96      #ifdef _WIN32
97      if (!IsSupportedName(s))
98        s = (UString)L"_" + s;
99      #endif
100      i++;
101    }
102  }
103}
104
105UString MakePathNameFromParts(const UStringVector &parts)
106{
107  UString result;
108  for (int i = 0; i < parts.Size(); i++)
109  {
110    if (i != 0)
111      result += WCHAR_PATH_SEPARATOR;
112    result += parts[i];
113  }
114  return result;
115}
116
117UString GetCorrectFsPath(const UString &path)
118{
119  UString res = GetCorrectFileName(path);
120  #ifdef _WIN32
121  if (!IsSupportedName(res))
122    res = (UString)L"_" + res;
123  #endif
124  return res;
125}
126
127UString GetCorrectFullFsPath(const UString &path)
128{
129  UStringVector parts;
130  SplitPathToParts(path, parts);
131  for (int i = 0; i < parts.Size(); i++)
132  {
133    UString &s = parts[i];
134    #ifdef _WIN32
135    while (!s.IsEmpty() && s[s.Length() - 1] == '.')
136      s.Delete(s.Length() - 1);
137    if (!IsSupportedName(s))
138      s = (UString)L"_" + s;
139    #endif
140  }
141  return MakePathNameFromParts(parts);
142}
143