1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
35 #define WIN32_LEAN_AND_MEAN
38 #include "sal/types.h"
42 WCHAR
* filename(WCHAR
* path
) {
44 for (WCHAR
* p
= path
;;) {
56 WCHAR
* path
, WCHAR
const * frontBegin
, WCHAR
const * frontEnd
,
57 WCHAR
const * backBegin
, std::size_t backLength
)
59 // Remove leading ".." segments in the second path together with matching
60 // segments in the first path that are neither empty nor "." nor ".." nor
61 // end in ":" (which is not foolprove, as it can erroneously erase the start
62 // of a UNC path, but only if the input is bad data):
63 while (backLength
>= 2 && backBegin
[0] == L
'.' && backBegin
[1] == L
'.' &&
64 (backLength
== 2 || backBegin
[2] == L
'\\'))
66 if (frontEnd
- frontBegin
< 2 || frontEnd
[-1] != L
'\\' ||
67 frontEnd
[-2] == L
'\\' || frontEnd
[-2] == L
':' ||
68 (frontEnd
[-2] == L
'.' &&
69 (frontEnd
- frontBegin
< 3 || frontEnd
[-3] == L
'\\' ||
70 (frontEnd
[-3] == L
'.' &&
71 (frontEnd
- frontBegin
< 4 || frontEnd
[-4] == L
'\\')))))
75 WCHAR
const * p
= frontEnd
- 1;
76 while (p
!= frontBegin
&& p
[-1] != L
'\\') {
79 if (p
== frontBegin
) {
83 if (backLength
== 2) {
92 static_cast< std::size_t >(MAX_PATH
- (frontEnd
- frontBegin
)))
93 // hopefully std::size_t is large enough
96 if (frontBegin
== path
) {
97 p
= const_cast< WCHAR
* >(frontEnd
);
100 while (frontBegin
!= frontEnd
) {
101 *p
++ = *frontBegin
++;
104 for (; backLength
> 0; --backLength
) {
110 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
115 WCHAR
* resolveLink(WCHAR
* path
) {
116 HANDLE h
= CreateFileW(
117 path
, FILE_READ_DATA
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
118 if (h
== INVALID_HANDLE_VALUE
) {
123 BOOL ok
= ReadFile(h
, p1
, MAX_PATH
, &n
, NULL
);
131 for (DWORD i
= 0; i
< n
;) {
132 unsigned char c
= static_cast< unsigned char >(p1
[i
++]);
135 SetLastError(ERROR_BAD_PATHNAME
);
139 if (n2
== MAX_PATH
) {
140 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
149 // Convert from UTF-8 to UTF-16:
152 } else if (c
>= 0xC2 && c
<= 0xDF && i
< n
&&
153 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
154 static_cast< unsigned char >(p1
[i
]) <= 0xBF)
156 p2
[n2
++] = ((c
& 0x1F) << 6) |
157 (static_cast< unsigned char >(p1
[i
++]) & 0x3F);
158 } else if (n
- i
> 1 &&
160 static_cast< unsigned char >(p1
[i
]) >= 0xA0 &&
161 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
162 ((c
>= 0xE1 && c
<= 0xEC || c
>= 0xEE && c
<= 0xEF) &&
163 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
164 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
166 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
167 static_cast< unsigned char >(p1
[i
]) <= 0x9F)) &&
168 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
169 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF)
171 p2
[n2
++] = ((c
& 0x0F) << 12) |
172 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 6) |
173 (static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F);
175 } else if (n
- 2 > 1 &&
177 static_cast< unsigned char >(p1
[i
]) >= 0x90 &&
178 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
179 (c
>= 0xF1 && c
<= 0xF3 &&
180 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
181 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
183 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
184 static_cast< unsigned char >(p1
[i
]) <= 0x8F)) &&
185 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
186 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF &&
187 static_cast< unsigned char >(p1
[i
+ 2]) >= 0x80 &&
188 static_cast< unsigned char >(p1
[i
+ 2]) <= 0xBF)
190 sal_Int32 u
= ((c
& 0x07) << 18) |
191 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 12) |
192 ((static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F) << 6) |
193 (static_cast< unsigned char >(p1
[i
+ 2]) & 0x3F);
195 p2
[n2
++] = static_cast< WCHAR
>(((u
- 0x10000) >> 10) | 0xD800);
196 p2
[n2
++] = static_cast< WCHAR
>(
197 ((u
- 0x10000) & 0x3FF) | 0xDC00);
199 SetLastError(ERROR_BAD_PATHNAME
);
206 if (colon
|| p2
[0] == L
'\\') {
207 // Interpret p2 as an absolute path:
210 // Interpret p2 as a relative path:
211 end
= filename(path
);
213 return buildPath(path
, path
, end
, p2
, n2
);
220 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */