aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/uriutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/uriutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/uriutil.cpp553
1 files changed, 553 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/uriutil.cpp b/src/libs/dutil/WixToolset.DUtil/uriutil.cpp
new file mode 100644
index 00000000..7913c22e
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/uriutil.cpp
@@ -0,0 +1,553 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// Exit macros
7#define UriExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
8#define UriExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
9#define UriExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
10#define UriExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
11#define UriExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
12#define UriExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_URIUTIL, x, s, __VA_ARGS__)
13#define UriExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_URIUTIL, p, x, e, s, __VA_ARGS__)
14#define UriExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_URIUTIL, p, x, s, __VA_ARGS__)
15#define UriExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_URIUTIL, p, x, e, s, __VA_ARGS__)
16#define UriExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_URIUTIL, p, x, s, __VA_ARGS__)
17#define UriExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_URIUTIL, e, x, s, __VA_ARGS__)
18#define UriExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_URIUTIL, g, x, s, __VA_ARGS__)
19
20
21//
22// UriCanonicalize - canonicalizes a URI.
23//
24extern "C" HRESULT DAPI UriCanonicalize(
25 __inout_z LPWSTR* psczUri
26 )
27{
28 HRESULT hr = S_OK;
29 WCHAR wz[INTERNET_MAX_URL_LENGTH] = { };
30 DWORD cch = countof(wz);
31
32 if (!::InternetCanonicalizeUrlW(*psczUri, wz, &cch, ICU_DECODE))
33 {
34 UriExitWithLastError(hr, "Failed to canonicalize URI.");
35 }
36
37 hr = StrAllocString(psczUri, wz, cch);
38 UriExitOnFailure(hr, "Failed copy canonicalized URI.");
39
40LExit:
41 return hr;
42}
43
44
45//
46// UriCrack - cracks a URI into constituent parts.
47//
48extern "C" HRESULT DAPI UriCrack(
49 __in_z LPCWSTR wzUri,
50 __out_opt INTERNET_SCHEME* pScheme,
51 __deref_opt_out_z LPWSTR* psczHostName,
52 __out_opt INTERNET_PORT* pPort,
53 __deref_opt_out_z LPWSTR* psczUser,
54 __deref_opt_out_z LPWSTR* psczPassword,
55 __deref_opt_out_z LPWSTR* psczPath,
56 __deref_opt_out_z LPWSTR* psczQueryString
57 )
58{
59 HRESULT hr = S_OK;
60 URL_COMPONENTSW components = { };
61 WCHAR wzHostName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
62 WCHAR wzUserName[INTERNET_MAX_USER_NAME_LENGTH + 1];
63 WCHAR wzPassword[INTERNET_MAX_PASSWORD_LENGTH + 1];
64 WCHAR wzPath[INTERNET_MAX_PATH_LENGTH + 1];
65 WCHAR wzQueryString[INTERNET_MAX_PATH_LENGTH + 1];
66
67 components.dwStructSize = sizeof(URL_COMPONENTSW);
68
69 if (psczHostName)
70 {
71 components.lpszHostName = wzHostName;
72 components.dwHostNameLength = countof(wzHostName);
73 }
74
75 if (psczUser)
76 {
77 components.lpszUserName = wzUserName;
78 components.dwUserNameLength = countof(wzUserName);
79 }
80
81 if (psczPassword)
82 {
83 components.lpszPassword = wzPassword;
84 components.dwPasswordLength = countof(wzPassword);
85 }
86
87 if (psczPath)
88 {
89 components.lpszUrlPath = wzPath;
90 components.dwUrlPathLength = countof(wzPath);
91 }
92
93 if (psczQueryString)
94 {
95 components.lpszExtraInfo = wzQueryString;
96 components.dwExtraInfoLength = countof(wzQueryString);
97 }
98
99 if (!::InternetCrackUrlW(wzUri, 0, ICU_DECODE | ICU_ESCAPE, &components))
100 {
101 UriExitWithLastError(hr, "Failed to crack URI.");
102 }
103
104 if (pScheme)
105 {
106 *pScheme = components.nScheme;
107 }
108
109 if (psczHostName)
110 {
111 hr = StrAllocString(psczHostName, components.lpszHostName, components.dwHostNameLength);
112 UriExitOnFailure(hr, "Failed to copy host name.");
113 }
114
115 if (pPort)
116 {
117 *pPort = components.nPort;
118 }
119
120 if (psczUser)
121 {
122 hr = StrAllocString(psczUser, components.lpszUserName, components.dwUserNameLength);
123 UriExitOnFailure(hr, "Failed to copy user name.");
124 }
125
126 if (psczPassword)
127 {
128 hr = StrAllocString(psczPassword, components.lpszPassword, components.dwPasswordLength);
129 UriExitOnFailure(hr, "Failed to copy password.");
130 }
131
132 if (psczPath)
133 {
134 hr = StrAllocString(psczPath, components.lpszUrlPath, components.dwUrlPathLength);
135 UriExitOnFailure(hr, "Failed to copy path.");
136 }
137
138 if (psczQueryString)
139 {
140 hr = StrAllocString(psczQueryString, components.lpszExtraInfo, components.dwExtraInfoLength);
141 UriExitOnFailure(hr, "Failed to copy query string.");
142 }
143
144LExit:
145 return hr;
146}
147
148
149//
150// UriCrackEx - cracks a URI into URI_INFO.
151//
152extern "C" HRESULT DAPI UriCrackEx(
153 __in_z LPCWSTR wzUri,
154 __in URI_INFO* pUriInfo
155 )
156{
157 HRESULT hr = S_OK;
158
159 hr = UriCrack(wzUri, &pUriInfo->scheme, &pUriInfo->sczHostName, &pUriInfo->port, &pUriInfo->sczUser, &pUriInfo->sczPassword, &pUriInfo->sczPath, &pUriInfo->sczQueryString);
160 UriExitOnFailure(hr, "Failed to crack URI.");
161
162LExit:
163 return hr;
164}
165
166
167//
168// UriInfoUninitialize - frees the memory in a URI_INFO struct.
169//
170extern "C" void DAPI UriInfoUninitialize(
171 __in URI_INFO* pUriInfo
172 )
173{
174 ReleaseStr(pUriInfo->sczHostName);
175 ReleaseStr(pUriInfo->sczUser);
176 ReleaseStr(pUriInfo->sczPassword);
177 ReleaseStr(pUriInfo->sczPath);
178 ReleaseStr(pUriInfo->sczQueryString);
179 memset(pUriInfo, 0, sizeof(URI_INFO));
180}
181
182
183//
184// UriCreate - creates a URI from constituent parts.
185//
186extern "C" HRESULT DAPI UriCreate(
187 __inout_z LPWSTR* psczUri,
188 __in INTERNET_SCHEME scheme,
189 __in_z_opt LPWSTR wzHostName,
190 __in INTERNET_PORT port,
191 __in_z_opt LPWSTR wzUser,
192 __in_z_opt LPWSTR wzPassword,
193 __in_z_opt LPWSTR wzPath,
194 __in_z_opt LPWSTR wzQueryString
195 )
196{
197 HRESULT hr = S_OK;
198 WCHAR wz[INTERNET_MAX_URL_LENGTH] = { };
199 DWORD cch = countof(wz);
200 URL_COMPONENTSW components = { };
201
202 components.dwStructSize = sizeof(URL_COMPONENTSW);
203 components.nScheme = scheme;
204 components.lpszHostName = wzHostName;
205 components.nPort = port;
206 components.lpszUserName = wzUser;
207 components.lpszPassword = wzPassword;
208 components.lpszUrlPath = wzPath;
209 components.lpszExtraInfo = wzQueryString;
210
211 if (!::InternetCreateUrlW(&components, ICU_ESCAPE, wz, &cch))
212 {
213 UriExitWithLastError(hr, "Failed to create URI.");
214 }
215
216 hr = StrAllocString(psczUri, wz, cch);
217 UriExitOnFailure(hr, "Failed copy created URI.");
218
219LExit:
220 return hr;
221}
222
223
224//
225// UriGetServerAndResource - gets the server and resource as independent strings from a URI.
226//
227// NOTE: This function is useful for the InternetConnect/HttpRequest APIs.
228//
229extern "C" HRESULT DAPI UriGetServerAndResource(
230 __in_z LPCWSTR wzUri,
231 __out_z LPWSTR* psczServer,
232 __out_z LPWSTR* psczResource
233 )
234{
235 HRESULT hr = S_OK;
236 INTERNET_SCHEME scheme = INTERNET_SCHEME_UNKNOWN;
237 LPWSTR sczHostName = NULL;
238 INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER;
239 LPWSTR sczUser = NULL;
240 LPWSTR sczPassword = NULL;
241 LPWSTR sczPath = NULL;
242 LPWSTR sczQueryString = NULL;
243
244 hr = UriCrack(wzUri, &scheme, &sczHostName, &port, &sczUser, &sczPassword, &sczPath, &sczQueryString);
245 UriExitOnFailure(hr, "Failed to crack URI.");
246
247 hr = UriCreate(psczServer, scheme, sczHostName, port, sczUser, sczPassword, NULL, NULL);
248 UriExitOnFailure(hr, "Failed to allocate server URI.");
249
250 hr = UriCreate(psczResource, INTERNET_SCHEME_UNKNOWN, NULL, INTERNET_INVALID_PORT_NUMBER, NULL, NULL, sczPath, sczQueryString);
251 UriExitOnFailure(hr, "Failed to allocate resource URI.");
252
253LExit:
254 ReleaseStr(sczQueryString);
255 ReleaseStr(sczPath);
256 ReleaseStr(sczPassword);
257 ReleaseStr(sczUser);
258 ReleaseStr(sczHostName);
259
260 return hr;
261}
262
263
264//
265// UriFile - returns the file part of the URI.
266//
267extern "C" HRESULT DAPI UriFile(
268 __deref_out_z LPWSTR* psczFile,
269 __in_z LPCWSTR wzUri
270 )
271{
272 HRESULT hr = S_OK;
273 WCHAR wz[MAX_PATH + 1];
274 DWORD cch = countof(wz);
275 URL_COMPONENTSW uc = { };
276
277 uc.dwStructSize = sizeof(uc);
278 uc.lpszUrlPath = wz;
279 uc.dwUrlPathLength = cch;
280
281 if (!::InternetCrackUrlW(wzUri, 0, ICU_DECODE | ICU_ESCAPE, &uc))
282 {
283 UriExitWithLastError(hr, "Failed to crack URI.");
284 }
285
286 // Copy only the file name. Fortunately, PathFile() understands that
287 // forward slashes can be directory separators like backslashes.
288 hr = StrAllocString(psczFile, PathFile(wz), 0);
289 UriExitOnFailure(hr, "Failed to copy file name");
290
291LExit:
292 return hr;
293}
294
295
296/*******************************************************************
297 UriProtocol - determines the protocol of a URI.
298
299********************************************************************/
300extern "C" HRESULT DAPI UriProtocol(
301 __in_z LPCWSTR wzUri,
302 __out URI_PROTOCOL* pProtocol
303 )
304{
305 Assert(wzUri && *wzUri);
306 Assert(pProtocol);
307
308 HRESULT hr = S_OK;
309
310 if ((L'h' == wzUri[0] || L'H' == wzUri[0]) &&
311 (L't' == wzUri[1] || L'T' == wzUri[1]) &&
312 (L't' == wzUri[2] || L'T' == wzUri[2]) &&
313 (L'p' == wzUri[3] || L'P' == wzUri[3]) &&
314 (L's' == wzUri[4] || L'S' == wzUri[4]) &&
315 L':' == wzUri[5] &&
316 L'/' == wzUri[6] &&
317 L'/' == wzUri[7])
318 {
319 *pProtocol = URI_PROTOCOL_HTTPS;
320 }
321 else if ((L'h' == wzUri[0] || L'H' == wzUri[0]) &&
322 (L't' == wzUri[1] || L'T' == wzUri[1]) &&
323 (L't' == wzUri[2] || L'T' == wzUri[2]) &&
324 (L'p' == wzUri[3] || L'P' == wzUri[3]) &&
325 L':' == wzUri[4] &&
326 L'/' == wzUri[5] &&
327 L'/' == wzUri[6])
328 {
329 *pProtocol = URI_PROTOCOL_HTTP;
330 }
331 else if ((L'f' == wzUri[0] || L'F' == wzUri[0]) &&
332 (L't' == wzUri[1] || L'T' == wzUri[1]) &&
333 (L'p' == wzUri[2] || L'P' == wzUri[2]) &&
334 L':' == wzUri[3] &&
335 L'/' == wzUri[4] &&
336 L'/' == wzUri[5])
337 {
338 *pProtocol = URI_PROTOCOL_FTP;
339 }
340 else if ((L'f' == wzUri[0] || L'F' == wzUri[0]) &&
341 (L'i' == wzUri[1] || L'I' == wzUri[1]) &&
342 (L'l' == wzUri[2] || L'L' == wzUri[2]) &&
343 (L'e' == wzUri[3] || L'E' == wzUri[3]) &&
344 L':' == wzUri[4] &&
345 L'/' == wzUri[5] &&
346 L'/' == wzUri[6])
347 {
348 *pProtocol = URI_PROTOCOL_FILE;
349 }
350 else
351 {
352 *pProtocol = URI_PROTOCOL_UNKNOWN;
353 }
354
355 return hr;
356}
357
358
359/*******************************************************************
360 UriRoot - returns the root of the path specified in the URI.
361
362 examples:
363 file:///C:\path\path -> C:\
364 file://server/share/path/path -> \\server\share
365 http://www.example.com/path/path -> http://www.example.com/
366 ftp://ftp.example.com/path/path -> ftp://www.example.com/
367
368 NOTE: This function should only be used on cannonicalized URIs.
369 It does not cannonicalize itself.
370********************************************************************/
371extern "C" HRESULT DAPI UriRoot(
372 __in_z LPCWSTR wzUri,
373 __out LPWSTR* ppwzRoot,
374 __out_opt URI_PROTOCOL* pProtocol
375 )
376{
377 Assert(wzUri && *wzUri);
378 Assert(ppwzRoot);
379
380 HRESULT hr = S_OK;
381 URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN;
382 LPCWSTR pwcSlash = NULL;
383
384 hr = UriProtocol(wzUri, &protocol);
385 UriExitOnFailure(hr, "Invalid URI.");
386
387 switch (protocol)
388 {
389 case URI_PROTOCOL_FILE:
390 if (L'/' == wzUri[7]) // file path
391 {
392 if (((L'a' <= wzUri[8] && L'z' >= wzUri[8]) || (L'A' <= wzUri[8] && L'Z' >= wzUri[8])) && L':' == wzUri[9])
393 {
394 hr = StrAlloc(ppwzRoot, 4);
395 UriExitOnFailure(hr, "Failed to allocate string for root of URI.");
396 *ppwzRoot[0] = wzUri[8];
397 *ppwzRoot[1] = L':';
398 *ppwzRoot[2] = L'\\';
399 *ppwzRoot[3] = L'\0';
400 }
401 else
402 {
403 hr = E_INVALIDARG;
404 UriExitOnFailure(hr, "Invalid file path in URI.");
405 }
406 }
407 else // UNC share
408 {
409 pwcSlash = wcschr(wzUri + 8, L'/');
410 if (!pwcSlash)
411 {
412 hr = E_INVALIDARG;
413 UriExitOnFailure(hr, "Invalid server name in URI.");
414 }
415 else
416 {
417 hr = StrAllocString(ppwzRoot, L"\\\\", 64);
418 UriExitOnFailure(hr, "Failed to allocate string for root of URI.");
419
420 pwcSlash = wcschr(pwcSlash + 1, L'/');
421 if (pwcSlash)
422 {
423 hr = StrAllocConcat(ppwzRoot, wzUri + 8, pwcSlash - wzUri - 8);
424 UriExitOnFailure(hr, "Failed to add server/share to root of URI.");
425 }
426 else
427 {
428 hr = StrAllocConcat(ppwzRoot, wzUri + 8, 0);
429 UriExitOnFailure(hr, "Failed to add server/share to root of URI.");
430 }
431
432 // replace all slashes with backslashes to be truly UNC.
433 for (LPWSTR pwc = *ppwzRoot; pwc && *pwc; ++pwc)
434 {
435 if (L'/' == *pwc)
436 {
437 *pwc = L'\\';
438 }
439 }
440 }
441 }
442 break;
443
444 case URI_PROTOCOL_FTP:
445 pwcSlash = wcschr(wzUri + 6, L'/');
446 if (pwcSlash)
447 {
448 hr = StrAllocString(ppwzRoot, wzUri, pwcSlash - wzUri);
449 UriExitOnFailure(hr, "Failed allocate root from URI.");
450 }
451 else
452 {
453 hr = StrAllocString(ppwzRoot, wzUri, 0);
454 UriExitOnFailure(hr, "Failed allocate root from URI.");
455 }
456 break;
457
458 case URI_PROTOCOL_HTTP:
459 pwcSlash = wcschr(wzUri + 7, L'/');
460 if (pwcSlash)
461 {
462 hr = StrAllocString(ppwzRoot, wzUri, pwcSlash - wzUri);
463 UriExitOnFailure(hr, "Failed allocate root from URI.");
464 }
465 else
466 {
467 hr = StrAllocString(ppwzRoot, wzUri, 0);
468 UriExitOnFailure(hr, "Failed allocate root from URI.");
469 }
470 break;
471
472 default:
473 hr = E_INVALIDARG;
474 UriExitOnFailure(hr, "Unknown URI protocol.");
475 }
476
477 if (pProtocol)
478 {
479 *pProtocol = protocol;
480 }
481
482LExit:
483 return hr;
484}
485
486
487extern "C" HRESULT DAPI UriResolve(
488 __in_z LPCWSTR wzUri,
489 __in_opt LPCWSTR wzBaseUri,
490 __out LPWSTR* ppwzResolvedUri,
491 __out_opt URI_PROTOCOL* pResolvedProtocol
492 )
493{
494 UNREFERENCED_PARAMETER(wzUri);
495 UNREFERENCED_PARAMETER(wzBaseUri);
496 UNREFERENCED_PARAMETER(ppwzResolvedUri);
497 UNREFERENCED_PARAMETER(pResolvedProtocol);
498
499 HRESULT hr = E_NOTIMPL;
500#if 0
501 URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN;
502
503 hr = UriProtocol(wzUri, &protocol);
504 UriExitOnFailure(hr, "Failed to determine protocol for URL: %ls", wzUri);
505
506 UriExitOnNull(ppwzResolvedUri, hr, E_INVALIDARG, "Failed to resolve URI, because no method of output was provided");
507
508 if (URI_PROTOCOL_UNKNOWN == protocol)
509 {
510 UriExitOnNull(wzBaseUri, hr, E_INVALIDARG, "Failed to resolve URI - base URI provided was NULL");
511
512 if (L'/' == *wzUri || L'\\' == *wzUri)
513 {
514 hr = UriRoot(wzBaseUri, ppwzResolvedUri, &protocol);
515 UriExitOnFailure(hr, "Failed to get root from URI: %ls", wzBaseUri);
516
517 hr = StrAllocConcat(ppwzResolvedUri, wzUri, 0);
518 UriExitOnFailure(hr, "Failed to concat file to base URI.");
519 }
520 else
521 {
522 hr = UriProtocol(wzBaseUri, &protocol);
523 UriExitOnFailure(hr, "Failed to get protocol of base URI: %ls", wzBaseUri);
524
525 LPCWSTR pwcFile = const_cast<LPCWSTR> (UriFile(wzBaseUri));
526 if (!pwcFile)
527 {
528 hr = E_INVALIDARG;
529 UriExitOnFailure(hr, "Failed to get file from base URI: %ls", wzBaseUri);
530 }
531
532 hr = StrAllocString(ppwzResolvedUri, wzBaseUri, pwcFile - wzBaseUri);
533 UriExitOnFailure(hr, "Failed to allocate string for resolved URI.");
534
535 hr = StrAllocConcat(ppwzResolvedUri, wzUri, 0);
536 UriExitOnFailure(hr, "Failed to concat file to resolved URI.");
537 }
538 }
539 else
540 {
541 hr = StrAllocString(ppwzResolvedUri, wzUri, 0);
542 UriExitOnFailure(hr, "Failed to copy resolved URI.");
543 }
544
545 if (pResolvedProtocol)
546 {
547 *pResolvedProtocol = protocol;
548 }
549
550LExit:
551#endif
552 return hr;
553}