xref: /aoo4110/main/cli_ure/source/native/path.cxx (revision b1cdbd2c)
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