Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(202)

Side by Side Diff: base/path.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/path.h ('k') | base/path_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15 //
16 // Path utility functions.
17
18 #include "omaha/base/path.h"
19
20 #include <atlbase.h>
21 #include <atlstr.h>
22 #include <atlpath.h>
23 #include <map>
24 #include <vector>
25 #include "omaha/base/error.h"
26 #include "omaha/base/file.h"
27 #include "omaha/base/shell.h"
28 #include "omaha/base/string.h"
29 #include "omaha/base/utils.h"
30
31 namespace omaha {
32
33 const TCHAR* const kRegSvr32Cmd1 = _T("regsvr32 ");
34 const TCHAR* const kRegSvr32Cmd2 = _T("regsvr32.exe ");
35 const TCHAR* const kRunDll32Cmd1 = _T("rundll32 ");
36 const TCHAR* const kRunDll32Cmd2 = _T("rundll32.exe ");
37 const TCHAR* const kMsiExecCmd1 = _T("msiexec ");
38 const TCHAR* const kMsiExecCmd2 = _T("msiexec.exe ");
39 const TCHAR* const kDotExe = _T(".exe");
40
41
42 namespace detail {
43
44 typedef bool (*Filter)(const WIN32_FIND_DATA&);
45
46 bool IsFile(const WIN32_FIND_DATA& find_data) {
47 return (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
48 }
49
50 bool IsDirectory(const WIN32_FIND_DATA& find_data) {
51 return (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
52 }
53
54 bool AllFiles(const WIN32_FIND_DATA&) {
55 return true;
56 }
57
58 HRESULT FindFilesEx(const CString& dir,
59 const CString& pattern,
60 std::vector<CString>* files,
61 Filter func) {
62 ASSERT1(files);
63
64 files->clear();
65 if (!File::Exists(dir)) {
66 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
67 }
68
69 CString files_to_find = ConcatenatePath(dir, pattern);
70 WIN32_FIND_DATA find_data = {0};
71 scoped_hfind hfind(::FindFirstFile(files_to_find, &find_data));
72 if (!hfind) {
73 HRESULT hr = HRESULTFromLastError();
74 UTIL_LOG(L5, (_T("[File::GetWildcards - FindFirstFile failed][0x%x]"), hr));
75 return hr;
76 }
77
78 do {
79 if (func(find_data)) {
80 files->push_back(find_data.cFileName);
81 }
82 } while (::FindNextFile(get(hfind), &find_data));
83
84 return S_OK;
85 }
86
87 } // namespace detail.
88
89 // Get the starting path from the command string
90 CString GetStartingPathFromString(const CString& s) {
91 CString path;
92 CString str(s);
93 TrimCString(str);
94
95 int len = str.GetLength();
96 if (len > 0) {
97 if (str[0] == _T('"')) {
98 // For something like: "c:\Program Files\...\" ...
99 int idx = String_FindChar(str.GetString() + 1, _T('"'));
100 if (idx != -1)
101 path.SetString(str.GetString() + 1, idx);
102 } else {
103 // For something like: c:\PRGRA~1\... ...
104 int idx = String_FindChar(str, _T(' '));
105 path.SetString(str, idx == -1 ? len : idx);
106 }
107 }
108
109 return path;
110 }
111
112 // Get the trailing path from the command string
113 CString GetTrailingPathFromString(const CString& s) {
114 CString path;
115 CString str(s);
116 TrimCString(str);
117
118 int len = str.GetLength();
119 if (len > 0) {
120 if (str[len - 1] == _T('"')) {
121 // For something like: regsvr32 /u /s "c:\Program Files\..."
122 str.Truncate(len - 1);
123 int idx = String_ReverseFindChar(str, _T('"'));
124 if (idx != -1)
125 path.SetString(str.GetString() + idx + 1, len - idx - 1);
126 } else {
127 // For something like: regsvr32 /u /s c:\PRGRA~1\...
128 int idx = String_ReverseFindChar(str, _T(' '));
129 if (idx != -1)
130 path.SetString(str.GetString() + idx + 1, len - idx - 1);
131 }
132 }
133
134 return path;
135 }
136
137 // Get the file from the command string
138 HRESULT GetFileFromCommandString(const TCHAR* s, CString* file) {
139 ASSERT1(file);
140
141 if (!s || !*s) {
142 return E_INVALIDARG;
143 }
144
145 CString str(s);
146 TrimCString(str);
147
148 // Handle the string starting with quotation mark
149 // For example: "C:\Program Files\WinZip\WINZIP32.EXE" /uninstall
150 if (str[0] == _T('"')) {
151 int idx_quote = str.Find(_T('"'), 1);
152 if (idx_quote != -1) {
153 file->SetString(str.GetString() + 1, idx_quote - 1);
154 return S_OK;
155 } else {
156 return E_FAIL;
157 }
158 }
159
160 // Handle the string starting with "regsvr32"
161 // For example: regsvr32 /u /s "c:\program files\google\googletoolbar3.dll"
162 if (String_StartsWith(str, kRegSvr32Cmd1, true) ||
163 String_StartsWith(str, kRegSvr32Cmd2, true)) {
164 file->SetString(GetTrailingPathFromString(str));
165 return S_OK;
166 }
167
168 // Handle the string starting with "rundll32"
169 // For example: "rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 C:\WINDOWS\INF\PCHealth.inf" // NOLINT
170 if (String_StartsWith(str, kRunDll32Cmd1, true) ||
171 String_StartsWith(str, kRunDll32Cmd2, true)) {
172 int idx_space = str.Find(_T(' '));
173 ASSERT1(idx_space != -1);
174 int idx_comma = str.Find(_T(','), idx_space + 1);
175 if (idx_comma != -1) {
176 file->SetString(str.GetString() + idx_space + 1,
177 idx_comma - idx_space - 1);
178 TrimCString(*file);
179 return S_OK;
180 } else {
181 return E_FAIL;
182 }
183 }
184
185 // Handle the string starting with "msiexec"
186 // For example: MsiExec.exe /I{25A13826-8E4A-4FBF-AD2B-776447FE9646}
187 if (String_StartsWith(str, kMsiExecCmd1, true) ||
188 String_StartsWith(str, kMsiExecCmd2, true)) {
189 return E_FAIL;
190 }
191
192 // Otherwise, try to find the file till reaching ".exe"
193 // For example: "C:\Program Files\Google\Google Desktop Search\GoogleDesktopSe tup.exe -uninstall" // NOLINT
194 for (int i = 0; i < str.GetLength(); ++i) {
195 if (String_StartsWith(str.GetString() + i, kDotExe, true)) {
196 file->SetString(str, i + _tcslen(kDotExe));
197 return S_OK;
198 }
199 }
200
201 // As last resort, return the part from the beginning to first space found.
202 int idx = str.Find(_T(' '));
203 if (idx == -1) {
204 file->SetString(str);
205 } else {
206 file->SetString(str, idx);
207 }
208
209 return S_OK;
210 }
211
212 // Expands the string with embedded special folder variables.
213 // TODO(omaha): This function seems to have a very specific purpose, which
214 // is not used in our code base. Consider removing it.
215 HRESULT ExpandStringWithSpecialFolders(CString* str) {
216 ASSERT(str, (L""));
217
218 #pragma warning(push)
219 // construction of local static object is not thread-safe
220 #pragma warning(disable : 4640)
221 static std::map<CString, CString> g_special_folders_mapping;
222 #pragma warning(pop)
223
224 if (g_special_folders_mapping.size() == 0) {
225 RET_IF_FAILED(
226 Shell::GetSpecialFolderKeywordsMapping(&g_special_folders_mapping));
227 }
228
229 CString expanded_str;
230 RET_IF_FAILED(
231 ExpandEnvLikeStrings(*str, g_special_folders_mapping, &expanded_str));
232
233 str->SetString(expanded_str);
234
235 return S_OK;
236 }
237
238 // Internal helper method for normalizing a path
239 HRESULT NormalizePathInternal(const TCHAR* path, CString* normalized_path) {
240 // We use '|' to separate fields
241 CString field;
242 int bar_idx = String_FindChar(path, _T('|'));
243 if (bar_idx == -1)
244 field = path;
245 else
246 field.SetString(path, bar_idx);
247
248 if (IsRegistryPath(field)) {
249 CString key_name, value_name;
250 RET_IF_FAILED(RegSplitKeyvalueName(field, &key_name, &value_name));
251
252 CString reg_value;
253 RET_IF_FAILED(RegKey::GetValue(key_name, value_name, &reg_value));
254 normalized_path->Append(reg_value);
255 } else {
256 RET_IF_FAILED(ExpandStringWithSpecialFolders(&field));
257 normalized_path->Append(field);
258 }
259
260 if (bar_idx != -1)
261 return NormalizePathInternal(path + bar_idx + 1, normalized_path);
262 else
263 return S_OK;
264 }
265
266 // Normalize a path
267 HRESULT NormalizePath(const TCHAR* path, CString* normalized_path) {
268 ASSERT1(normalized_path);
269
270 normalized_path->Empty();
271
272 if (path) {
273 HRESULT hr = NormalizePathInternal(path, normalized_path);
274 if (FAILED(hr)) {
275 normalized_path->Empty();
276 UTIL_LOG(LE, (_T("[NormalizePath - unable to normalize path][%s][0x%x]"),
277 path, hr));
278 }
279 return hr;
280 } else {
281 return S_OK;
282 }
283 }
284
285 CString ConcatenatePath(const CString& path1, const CString& path2) {
286 CString ret(path1);
287
288 // Append the file path using the PathAppend.
289 VERIFY1(::PathAppend(CStrBuf(ret, MAX_PATH), path2));
290
291 return ret;
292 }
293
294 // Get the filename from the path
295 // "C:\TEST\sample.txt" returns "sample.txt"
296 CString GetFileFromPath(const CString& path) {
297 CPath path1(path);
298 path1.StripPath();
299 return static_cast<CString>(path1);
300 }
301
302 // Get the directory from the path
303 // "C:\TEST\sample.txt" returns "C:\TEST"
304 // Get the directory out of the file path
305 CString GetDirectoryFromPath(const CString& path) {
306 CPath path1(path);
307 path1.RemoveFileSpec();
308 return static_cast<CString>(path1);
309 }
310
311 // Remove the extension from the path.
312 // "C:\TEST\sample.txt" returns "C:\TEST\sample"
313 CString GetPathRemoveExtension(const CString& path) {
314 CPath path1(path);
315 path1.RemoveExtension();
316 return static_cast<CString>(path1);
317 }
318
319 // Basically, an absolute path starts with X:\ or \\ (a UNC name)
320 bool IsAbsolutePath(const TCHAR* path) {
321 ASSERT1(path);
322
323 int len = ::_tcslen(path);
324 if (len < 3)
325 return false;
326 if (*path == _T('"'))
327 path++;
328 if (String_StartsWith(path+1, _T(":\\"), false))
329 return true;
330 if (String_StartsWith(path, _T("\\\\"), false))
331 return true;
332 return false;
333 }
334
335 void EnclosePath(CString* path) {
336 ASSERT1(path);
337
338 if (path->IsEmpty()) {
339 return;
340 }
341
342 bool starts_with_quote = (_T('"') == path->GetAt(0));
343 bool ends_with_quote = (_T('"') == path->GetAt(path->GetLength() - 1));
344 ASSERT(starts_with_quote == ends_with_quote, (_T("%s"), path->GetString()));
345 bool is_enclosed = starts_with_quote && ends_with_quote;
346 if (is_enclosed) {
347 return;
348 }
349
350 path->Insert(0, _T('"'));
351 path->AppendChar(_T('"'));
352 }
353
354 CString EnclosePathIfExe(const CString& module_path) {
355 if (!String_EndsWith(module_path, _T(".exe"), true)) {
356 return module_path;
357 }
358
359 CString enclosed_path(module_path);
360 EnclosePath(&enclosed_path);
361 return enclosed_path;
362 }
363
364 // remove any double quotation masks from an enclosed path
365 void UnenclosePath(CString* path) {
366 ASSERT1(path);
367
368 if (path->GetLength() > 1 && path->GetAt(0) == _T('"')) {
369 bool right_quote_exists = (path->GetAt(path->GetLength() - 1) == _T('"'));
370 ASSERT(right_quote_exists,
371 (_T("[UnenclosePath - double quote mismatches]")));
372 if (right_quote_exists) {
373 // Remove the double quotation masks
374 path->Delete(0);
375 path->Truncate(path->GetLength() - 1);
376 }
377 }
378 }
379
380 void RemoveMismatchedEndQuoteInDirectoryPath(CString* directory_path) {
381 ASSERT1(directory_path);
382
383 if (directory_path->GetLength() <= 1) {
384 return;
385 }
386
387 ASSERT1(directory_path->GetAt(0) != _T('"'));
388 if (directory_path->GetAt(directory_path->GetLength() - 1) == _T('"')) {
389 directory_path->Truncate(directory_path->GetLength() - 1);
390 }
391 }
392
393 HRESULT ShortPathToLongPath(const CString& short_path, CString* long_path) {
394 ASSERT1(long_path);
395
396 TCHAR long_name[MAX_PATH] = {0};
397 if (!::GetLongPathName(short_path, long_name, MAX_PATH)) {
398 return HRESULTFromLastError();
399 }
400
401 *long_path = long_name;
402 return S_OK;
403 }
404
405 HRESULT FindFilesEx(const CString& dir,
406 const CString& pattern,
407 std::vector<CString>* files) {
408 return detail::FindFilesEx(dir, pattern, files, &detail::IsFile);
409 }
410
411 HRESULT FindFiles(const CString& dir,
412 const CString& pattern,
413 std::vector<CString>* files) {
414 return detail::FindFilesEx(dir, pattern, files, &detail::AllFiles);
415 }
416
417 HRESULT FindSubDirectories(const CString& dir,
418 const CString& pattern,
419 std::vector<CString>* files) {
420 return detail::FindFilesEx(dir, pattern, files, &detail::IsDirectory);
421 }
422
423 HRESULT FindFileRecursive(const CString& dir,
424 const CString& pattern,
425 std::vector<CString>* files) {
426 ASSERT1(files);
427
428 std::vector<CString> temp_files;
429 HRESULT hr = FindFilesEx(dir, pattern, &temp_files);
430 if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && FAILED(hr)) {
431 return hr;
432 }
433
434 for (size_t i = 0; i < temp_files.size(); ++i) {
435 files->push_back(ConcatenatePath(dir, temp_files[i]));
436 }
437
438 std::vector<CString> sub_dirs;
439 hr = FindSubDirectories(dir, _T("*"), &sub_dirs);
440 if (FAILED(hr)) {
441 return hr;
442 }
443
444 for (size_t i = 0; i < sub_dirs.size(); ++i) {
445 const CString& sub_dir = sub_dirs[i];
446 if (sub_dir == _T(".") || sub_dir == _T("..")) {
447 continue;
448 }
449
450 CString path = ConcatenatePath(dir, sub_dir);
451 hr = FindFileRecursive(path, pattern, files);
452 if (FAILED(hr)) {
453 return hr;
454 }
455 }
456
457 return S_OK;
458 }
459
460 } // namespace omaha
461
OLDNEW
« no previous file with comments | « base/path.h ('k') | base/path_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698