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