1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pathutils.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "precompiled_tools.hxx"
32 #include "sal/config.h"
38 #define WIN32_LEAN_AND_MEAN
41 #include "sal/types.h"
42 #include "tools/pathutils.hxx"
46 WCHAR
* filename(WCHAR
* path
) {
48 for (WCHAR
* p
= path
;;) {
60 WCHAR
* path
, WCHAR
const * frontBegin
, WCHAR
const * frontEnd
,
61 WCHAR
const * backBegin
, std::size_t backLength
)
63 // Remove leading ".." segments in the second path together with matching
64 // segments in the first path that are neither empty nor "." nor ".." nor
65 // end in ":" (which is not foolprove, as it can erroneously erase the start
66 // of a UNC path, but only if the input is bad data):
67 while (backLength
>= 2 && backBegin
[0] == L
'.' && backBegin
[1] == L
'.' &&
68 (backLength
== 2 || backBegin
[2] == L
'\\'))
70 if (frontEnd
- frontBegin
< 2 || frontEnd
[-1] != L
'\\' ||
71 frontEnd
[-2] == L
'\\' || frontEnd
[-2] == L
':' ||
72 (frontEnd
[-2] == L
'.' &&
73 (frontEnd
- frontBegin
< 3 || frontEnd
[-3] == L
'\\' ||
74 (frontEnd
[-3] == L
'.' &&
75 (frontEnd
- frontBegin
< 4 || frontEnd
[-4] == L
'\\')))))
79 WCHAR
const * p
= frontEnd
- 1;
80 while (p
!= frontBegin
&& p
[-1] != L
'\\') {
83 if (p
== frontBegin
) {
87 if (backLength
== 2) {
96 static_cast< std::size_t >(MAX_PATH
- (frontEnd
- frontBegin
)))
97 // hopefully std::size_t is large enough
100 if (frontBegin
== path
) {
101 p
= const_cast< WCHAR
* >(frontEnd
);
104 while (frontBegin
!= frontEnd
) {
105 *p
++ = *frontBegin
++;
108 for (; backLength
> 0; --backLength
) {
114 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
119 WCHAR
* resolveLink(WCHAR
* path
) {
120 HANDLE h
= CreateFileW(
121 path
, FILE_READ_DATA
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
122 if (h
== INVALID_HANDLE_VALUE
) {
127 BOOL ok
= ReadFile(h
, p1
, MAX_PATH
, &n
, NULL
);
135 for (DWORD i
= 0; i
< n
;) {
136 unsigned char c
= static_cast< unsigned char >(p1
[i
++]);
139 SetLastError(ERROR_BAD_PATHNAME
);
143 if (n2
== MAX_PATH
) {
144 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
153 // Convert from UTF-8 to UTF-16:
156 } else if (c
>= 0xC2 && c
<= 0xDF && i
< n
&&
157 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
158 static_cast< unsigned char >(p1
[i
]) <= 0xBF)
160 p2
[n2
++] = ((c
& 0x1F) << 6) |
161 (static_cast< unsigned char >(p1
[i
++]) & 0x3F);
162 } else if (n
- i
> 1 &&
164 static_cast< unsigned char >(p1
[i
]) >= 0xA0 &&
165 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
166 ((c
>= 0xE1 && c
<= 0xEC || c
>= 0xEE && c
<= 0xEF) &&
167 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
168 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
170 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
171 static_cast< unsigned char >(p1
[i
]) <= 0x9F)) &&
172 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
173 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF)
175 p2
[n2
++] = ((c
& 0x0F) << 12) |
176 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 6) |
177 (static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F);
179 } else if (n
- 2 > 1 &&
181 static_cast< unsigned char >(p1
[i
]) >= 0x90 &&
182 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
183 (c
>= 0xF1 && c
<= 0xF3 &&
184 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
185 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
187 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
188 static_cast< unsigned char >(p1
[i
]) <= 0x8F)) &&
189 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
190 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF &&
191 static_cast< unsigned char >(p1
[i
+ 2]) >= 0x80 &&
192 static_cast< unsigned char >(p1
[i
+ 2]) <= 0xBF)
194 sal_Int32 u
= ((c
& 0x07) << 18) |
195 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 12) |
196 ((static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F) << 6) |
197 (static_cast< unsigned char >(p1
[i
+ 2]) & 0x3F);
199 p2
[n2
++] = static_cast< WCHAR
>(((u
- 0x10000) >> 10) | 0xD800);
200 p2
[n2
++] = static_cast< WCHAR
>(
201 ((u
- 0x10000) & 0x3FF) | 0xDC00);
203 SetLastError(ERROR_BAD_PATHNAME
);
210 if (colon
|| p2
[0] == L
'\\') {
211 // Interpret p2 as an absolute path:
214 // Interpret p2 as a relative path:
215 end
= filename(path
);
217 return buildPath(path
, path
, end
, p2
, n2
);