1 // ArchiveName.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../../C/Sort.h"
6
7 #include "../../../Common/Wildcard.h"
8 #include "../../../Common/StringToInt.h"
9
10 #include "../../../Windows/FileDir.h"
11 #include "../../../Windows/FileName.h"
12
13 #include "ArchiveName.h"
14 #include "ExtractingFilePath.h"
15
16 using namespace NWindows;
17 using namespace NFile;
18
19
20 static const char *g_ArcExts =
21 "7z"
22 "\0" "zip"
23 "\0" "tar"
24 "\0" "wim"
25 "\0";
26
27 static const char *g_HashExts =
28 "sha256"
29 "\0";
30
31
CreateArchiveName(const UStringVector & paths,bool isHash,const NFind::CFileInfo * fi,UString & baseName)32 UString CreateArchiveName(
33 const UStringVector &paths,
34 bool isHash,
35 const NFind::CFileInfo *fi,
36 UString &baseName)
37 {
38 bool keepName = isHash;
39 /*
40 if (paths.Size() == 1)
41 {
42 const UString &name = paths[0];
43 if (name.Len() > 4)
44 if (CompareFileNames(name.RightPtr(4), L".tar") == 0)
45 keepName = true;
46 }
47 */
48
49 UString name ("Archive");
50 NFind::CFileInfo fi3;
51 if (paths.Size() > 1)
52 fi = NULL;
53 if (!fi && paths.Size() != 0)
54 {
55 const UString &path = paths.Front();
56 if (paths.Size() == 1)
57 {
58 if (fi3.Find(us2fs(path)))
59 fi = &fi3;
60 }
61 else
62 {
63 // we try to use name of parent folder
64 FString dirPrefix;
65 if (NDir::GetOnlyDirPrefix(us2fs(path), dirPrefix))
66 {
67 if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
68 {
69 #if defined(_WIN32) && !defined(UNDER_CE)
70 if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
71 {
72 if (path != fs2us(dirPrefix))
73 name = dirPrefix[dirPrefix.Len() - 3]; // only letter
74 }
75 else
76 #endif
77 {
78 dirPrefix.DeleteBack();
79 if (!dirPrefix.IsEmpty())
80 {
81 const int slash = dirPrefix.ReverseFind_PathSepar();
82 if (slash >= 0 && slash != (int)dirPrefix.Len() - 1)
83 name = dirPrefix.Ptr(slash + 1);
84 else if (fi3.Find(dirPrefix))
85 name = fs2us(fi3.Name);
86 }
87 }
88 }
89 }
90 }
91 }
92
93 if (fi)
94 {
95 name = fs2us(fi->Name);
96 if (!fi->IsDir() && !keepName)
97 {
98 const int dotPos = name.Find(L'.');
99 if (dotPos > 0 && name.Find(L'.', (unsigned)dotPos + 1) < 0)
100 name.DeleteFrom((unsigned)dotPos);
101 }
102 }
103 name = Get_Correct_FsFile_Name(name);
104
105 CRecordVector<UInt32> ids;
106 bool simple_IsAllowed = true;
107 // for (int y = 0; y < 10000; y++) // for debug
108 {
109 // ids.Clear();
110 UString n;
111
112 FOR_VECTOR (i, paths)
113 {
114 const UString &a = paths[i];
115 const int slash = a.ReverseFind_PathSepar();
116 // if (name.Len() >= a.Len() - slash + 1) continue;
117 const wchar_t *s = a.Ptr(slash + 1);
118 if (!IsPath1PrefixedByPath2(s, name))
119 continue;
120 s += name.Len();
121 const char *exts = isHash ? g_HashExts : g_ArcExts;
122
123 for (;;)
124 {
125 const char *ext = exts;
126 const unsigned len = MyStringLen(ext);
127 if (len == 0)
128 break;
129 exts += len + 1;
130 n = s;
131 if (n.Len() <= len)
132 continue;
133 if (!StringsAreEqualNoCase_Ascii(n.RightPtr(len), ext))
134 continue;
135 n.DeleteFrom(n.Len() - len);
136 if (n.Back() != '.')
137 continue;
138 n.DeleteBack();
139 if (n.IsEmpty())
140 {
141 simple_IsAllowed = false;
142 break;
143 }
144 if (n.Len() < 2)
145 continue;
146 if (n[0] != '_')
147 continue;
148 const wchar_t *end;
149 const UInt32 v = ConvertStringToUInt32(n.Ptr(1), &end);
150 if (*end != 0)
151 continue;
152 ids.Add(v);
153 break;
154 }
155 }
156 }
157
158 baseName = name;
159 if (!simple_IsAllowed)
160 {
161 HeapSort(ids.NonConstData(), ids.Size());
162 UInt32 v = 2;
163 const unsigned num = ids.Size();
164 for (unsigned i = 0; i < num; i++)
165 {
166 const UInt32 id = ids[i];
167 if (id > v)
168 break;
169 if (id == v)
170 v = id + 1;
171 }
172 name.Add_Char('_');
173 name.Add_UInt32(v);
174 }
175 return name;
176 }
177