1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski #include "sal/config.h"
25*b1cdbd2cSJim Jagielski
26*b1cdbd2cSJim Jagielski #if defined WNT
27*b1cdbd2cSJim Jagielski
28*b1cdbd2cSJim Jagielski #include <cstddef>
29*b1cdbd2cSJim Jagielski
30*b1cdbd2cSJim Jagielski #define WIN32_LEAN_AND_MEAN
31*b1cdbd2cSJim Jagielski #include <windows.h>
32*b1cdbd2cSJim Jagielski
33*b1cdbd2cSJim Jagielski #include "sal/types.h"
34*b1cdbd2cSJim Jagielski //#include "tools/pathutils.hxx"
35*b1cdbd2cSJim Jagielski
36*b1cdbd2cSJim Jagielski namespace cli_ure {
37*b1cdbd2cSJim Jagielski
filename(WCHAR * path)38*b1cdbd2cSJim Jagielski WCHAR * filename(WCHAR * path) {
39*b1cdbd2cSJim Jagielski WCHAR * f = path;
40*b1cdbd2cSJim Jagielski for (WCHAR * p = path;;) {
41*b1cdbd2cSJim Jagielski switch (*p++) {
42*b1cdbd2cSJim Jagielski case L'\0':
43*b1cdbd2cSJim Jagielski return f;
44*b1cdbd2cSJim Jagielski case L'\\':
45*b1cdbd2cSJim Jagielski f = p;
46*b1cdbd2cSJim Jagielski break;
47*b1cdbd2cSJim Jagielski }
48*b1cdbd2cSJim Jagielski }
49*b1cdbd2cSJim Jagielski }
50*b1cdbd2cSJim Jagielski
buildPath(WCHAR * path,WCHAR const * frontBegin,WCHAR const * frontEnd,WCHAR const * backBegin,std::size_t backLength)51*b1cdbd2cSJim Jagielski WCHAR * buildPath(
52*b1cdbd2cSJim Jagielski WCHAR * path, WCHAR const * frontBegin, WCHAR const * frontEnd,
53*b1cdbd2cSJim Jagielski WCHAR const * backBegin, std::size_t backLength)
54*b1cdbd2cSJim Jagielski {
55*b1cdbd2cSJim Jagielski // Remove leading ".." segments in the second path together with matching
56*b1cdbd2cSJim Jagielski // segments in the first path that are neither empty nor "." nor ".." nor
57*b1cdbd2cSJim Jagielski // end in ":" (which is not foolprove, as it can erroneously erase the start
58*b1cdbd2cSJim Jagielski // of a UNC path, but only if the input is bad data):
59*b1cdbd2cSJim Jagielski while (backLength >= 2 && backBegin[0] == L'.' && backBegin[1] == L'.' &&
60*b1cdbd2cSJim Jagielski (backLength == 2 || backBegin[2] == L'\\'))
61*b1cdbd2cSJim Jagielski {
62*b1cdbd2cSJim Jagielski if (frontEnd - frontBegin < 2 || frontEnd[-1] != L'\\' ||
63*b1cdbd2cSJim Jagielski frontEnd[-2] == L'\\' || frontEnd[-2] == L':' ||
64*b1cdbd2cSJim Jagielski (frontEnd[-2] == L'.' &&
65*b1cdbd2cSJim Jagielski (frontEnd - frontBegin < 3 || frontEnd[-3] == L'\\' ||
66*b1cdbd2cSJim Jagielski (frontEnd[-3] == L'.' &&
67*b1cdbd2cSJim Jagielski (frontEnd - frontBegin < 4 || frontEnd[-4] == L'\\')))))
68*b1cdbd2cSJim Jagielski {
69*b1cdbd2cSJim Jagielski break;
70*b1cdbd2cSJim Jagielski }
71*b1cdbd2cSJim Jagielski WCHAR const * p = frontEnd - 1;
72*b1cdbd2cSJim Jagielski while (p != frontBegin && p[-1] != L'\\') {
73*b1cdbd2cSJim Jagielski --p;
74*b1cdbd2cSJim Jagielski }
75*b1cdbd2cSJim Jagielski if (p == frontBegin) {
76*b1cdbd2cSJim Jagielski break;
77*b1cdbd2cSJim Jagielski }
78*b1cdbd2cSJim Jagielski frontEnd = p;
79*b1cdbd2cSJim Jagielski if (backLength == 2) {
80*b1cdbd2cSJim Jagielski backBegin += 2;
81*b1cdbd2cSJim Jagielski backLength -= 2;
82*b1cdbd2cSJim Jagielski } else {
83*b1cdbd2cSJim Jagielski backBegin += 3;
84*b1cdbd2cSJim Jagielski backLength -= 3;
85*b1cdbd2cSJim Jagielski }
86*b1cdbd2cSJim Jagielski }
87*b1cdbd2cSJim Jagielski if (backLength <
88*b1cdbd2cSJim Jagielski static_cast< std::size_t >(MAX_PATH - (frontEnd - frontBegin)))
89*b1cdbd2cSJim Jagielski // hopefully std::size_t is large enough
90*b1cdbd2cSJim Jagielski {
91*b1cdbd2cSJim Jagielski WCHAR * p;
92*b1cdbd2cSJim Jagielski if (frontBegin == path) {
93*b1cdbd2cSJim Jagielski p = const_cast< WCHAR * >(frontEnd);
94*b1cdbd2cSJim Jagielski } else {
95*b1cdbd2cSJim Jagielski p = path;
96*b1cdbd2cSJim Jagielski while (frontBegin != frontEnd) {
97*b1cdbd2cSJim Jagielski *p++ = *frontBegin++;
98*b1cdbd2cSJim Jagielski }
99*b1cdbd2cSJim Jagielski }
100*b1cdbd2cSJim Jagielski for (; backLength > 0; --backLength) {
101*b1cdbd2cSJim Jagielski *p++ = *backBegin++;
102*b1cdbd2cSJim Jagielski }
103*b1cdbd2cSJim Jagielski *p = L'\0';
104*b1cdbd2cSJim Jagielski return p;
105*b1cdbd2cSJim Jagielski } else {
106*b1cdbd2cSJim Jagielski SetLastError(ERROR_FILENAME_EXCED_RANGE);
107*b1cdbd2cSJim Jagielski return NULL;
108*b1cdbd2cSJim Jagielski }
109*b1cdbd2cSJim Jagielski }
110*b1cdbd2cSJim Jagielski
resolveLink(WCHAR * path)111*b1cdbd2cSJim Jagielski WCHAR * resolveLink(WCHAR * path) {
112*b1cdbd2cSJim Jagielski HANDLE h = CreateFileW(
113*b1cdbd2cSJim Jagielski path, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
114*b1cdbd2cSJim Jagielski if (h == INVALID_HANDLE_VALUE) {
115*b1cdbd2cSJim Jagielski return NULL;
116*b1cdbd2cSJim Jagielski }
117*b1cdbd2cSJim Jagielski char p1[MAX_PATH];
118*b1cdbd2cSJim Jagielski DWORD n;
119*b1cdbd2cSJim Jagielski BOOL ok = ReadFile(h, p1, MAX_PATH, &n, NULL);
120*b1cdbd2cSJim Jagielski CloseHandle(h);
121*b1cdbd2cSJim Jagielski if (!ok) {
122*b1cdbd2cSJim Jagielski return NULL;
123*b1cdbd2cSJim Jagielski }
124*b1cdbd2cSJim Jagielski WCHAR p2[MAX_PATH];
125*b1cdbd2cSJim Jagielski std::size_t n2 = 0;
126*b1cdbd2cSJim Jagielski bool colon = false;
127*b1cdbd2cSJim Jagielski for (DWORD i = 0; i < n;) {
128*b1cdbd2cSJim Jagielski unsigned char c = static_cast< unsigned char >(p1[i++]);
129*b1cdbd2cSJim Jagielski switch (c) {
130*b1cdbd2cSJim Jagielski case '\0':
131*b1cdbd2cSJim Jagielski SetLastError(ERROR_BAD_PATHNAME);
132*b1cdbd2cSJim Jagielski return NULL;
133*b1cdbd2cSJim Jagielski case '\x0A':
134*b1cdbd2cSJim Jagielski case '\x0D':
135*b1cdbd2cSJim Jagielski if (n2 == MAX_PATH) {
136*b1cdbd2cSJim Jagielski SetLastError(ERROR_FILENAME_EXCED_RANGE);
137*b1cdbd2cSJim Jagielski return NULL;
138*b1cdbd2cSJim Jagielski }
139*b1cdbd2cSJim Jagielski p2[n2] = L'\0';
140*b1cdbd2cSJim Jagielski break;
141*b1cdbd2cSJim Jagielski case ':':
142*b1cdbd2cSJim Jagielski colon = true;
143*b1cdbd2cSJim Jagielski // fall through
144*b1cdbd2cSJim Jagielski default:
145*b1cdbd2cSJim Jagielski // Convert from UTF-8 to UTF-16:
146*b1cdbd2cSJim Jagielski if (c <= 0x7F) {
147*b1cdbd2cSJim Jagielski p2[n2++] = c;
148*b1cdbd2cSJim Jagielski } else if (c >= 0xC2 && c <= 0xDF && i < n &&
149*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x80 &&
150*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0xBF)
151*b1cdbd2cSJim Jagielski {
152*b1cdbd2cSJim Jagielski p2[n2++] = ((c & 0x1F) << 6) |
153*b1cdbd2cSJim Jagielski (static_cast< unsigned char >(p1[i++]) & 0x3F);
154*b1cdbd2cSJim Jagielski } else if (n - i > 1 &&
155*b1cdbd2cSJim Jagielski ((c == 0xE0 &&
156*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0xA0 &&
157*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0xBF) ||
158*b1cdbd2cSJim Jagielski ((c >= 0xE1 && c <= 0xEC || c >= 0xEE && c <= 0xEF) &&
159*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x80 &&
160*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0xBF) ||
161*b1cdbd2cSJim Jagielski (c == 0xED &&
162*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x80 &&
163*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0x9F)) &&
164*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 1]) >= 0x80 &&
165*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 1]) <= 0xBF)
166*b1cdbd2cSJim Jagielski {
167*b1cdbd2cSJim Jagielski p2[n2++] = ((c & 0x0F) << 12) |
168*b1cdbd2cSJim Jagielski ((static_cast< unsigned char >(p1[i]) & 0x3F) << 6) |
169*b1cdbd2cSJim Jagielski (static_cast< unsigned char >(p1[i + 1]) & 0x3F);
170*b1cdbd2cSJim Jagielski i += 2;
171*b1cdbd2cSJim Jagielski } else if (n - 2 > 1 &&
172*b1cdbd2cSJim Jagielski ((c == 0xF0 &&
173*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x90 &&
174*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0xBF) ||
175*b1cdbd2cSJim Jagielski (c >= 0xF1 && c <= 0xF3 &&
176*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x80 &&
177*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0xBF) ||
178*b1cdbd2cSJim Jagielski (c == 0xF4 &&
179*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) >= 0x80 &&
180*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i]) <= 0x8F)) &&
181*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 1]) >= 0x80 &&
182*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 1]) <= 0xBF &&
183*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 2]) >= 0x80 &&
184*b1cdbd2cSJim Jagielski static_cast< unsigned char >(p1[i + 2]) <= 0xBF)
185*b1cdbd2cSJim Jagielski {
186*b1cdbd2cSJim Jagielski sal_Int32 u = ((c & 0x07) << 18) |
187*b1cdbd2cSJim Jagielski ((static_cast< unsigned char >(p1[i]) & 0x3F) << 12) |
188*b1cdbd2cSJim Jagielski ((static_cast< unsigned char >(p1[i + 1]) & 0x3F) << 6) |
189*b1cdbd2cSJim Jagielski (static_cast< unsigned char >(p1[i + 2]) & 0x3F);
190*b1cdbd2cSJim Jagielski i += 3;
191*b1cdbd2cSJim Jagielski p2[n2++] = static_cast< WCHAR >(((u - 0x10000) >> 10) | 0xD800);
192*b1cdbd2cSJim Jagielski p2[n2++] = static_cast< WCHAR >(
193*b1cdbd2cSJim Jagielski ((u - 0x10000) & 0x3FF) | 0xDC00);
194*b1cdbd2cSJim Jagielski } else {
195*b1cdbd2cSJim Jagielski SetLastError(ERROR_BAD_PATHNAME);
196*b1cdbd2cSJim Jagielski return NULL;
197*b1cdbd2cSJim Jagielski }
198*b1cdbd2cSJim Jagielski break;
199*b1cdbd2cSJim Jagielski }
200*b1cdbd2cSJim Jagielski }
201*b1cdbd2cSJim Jagielski WCHAR * end;
202*b1cdbd2cSJim Jagielski if (colon || p2[0] == L'\\') {
203*b1cdbd2cSJim Jagielski // Interpret p2 as an absolute path:
204*b1cdbd2cSJim Jagielski end = path;
205*b1cdbd2cSJim Jagielski } else {
206*b1cdbd2cSJim Jagielski // Interpret p2 as a relative path:
207*b1cdbd2cSJim Jagielski end = filename(path);
208*b1cdbd2cSJim Jagielski }
209*b1cdbd2cSJim Jagielski return buildPath(path, path, end, p2, n2);
210*b1cdbd2cSJim Jagielski }
211*b1cdbd2cSJim Jagielski
212*b1cdbd2cSJim Jagielski }
213*b1cdbd2cSJim Jagielski
214*b1cdbd2cSJim Jagielski #endif
215