1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
26 #define WIN32_LEAN_AND_MEAN
29 #include "sal/types.h"
33 SAL_DLLPUBLIC_EXPORT WCHAR
* filename(WCHAR
* path
) {
35 for (WCHAR
* p
= path
;;) {
47 WCHAR
* path
, WCHAR
const * frontBegin
, WCHAR
const * frontEnd
,
48 WCHAR
const * backBegin
, std::size_t backLength
)
50 // Remove leading ".." segments in the second path together with matching
51 // segments in the first path that are neither empty nor "." nor ".." nor
52 // end in ":" (which is not foolprove, as it can erroneously erase the start
53 // of a UNC path, but only if the input is bad data):
54 while (backLength
>= 2 && backBegin
[0] == L
'.' && backBegin
[1] == L
'.' &&
55 (backLength
== 2 || backBegin
[2] == L
'\\'))
57 if (frontEnd
- frontBegin
< 2 || frontEnd
[-1] != L
'\\' ||
58 frontEnd
[-2] == L
'\\' || frontEnd
[-2] == L
':' ||
59 (frontEnd
[-2] == L
'.' &&
60 (frontEnd
- frontBegin
< 3 || frontEnd
[-3] == L
'\\' ||
61 (frontEnd
[-3] == L
'.' &&
62 (frontEnd
- frontBegin
< 4 || frontEnd
[-4] == L
'\\')))))
66 WCHAR
const * p
= frontEnd
- 1;
67 while (p
!= frontBegin
&& p
[-1] != L
'\\') {
70 if (p
== frontBegin
) {
74 if (backLength
== 2) {
83 static_cast< std::size_t >(MAX_PATH
- (frontEnd
- frontBegin
)))
84 // hopefully std::size_t is large enough
87 if (frontBegin
== path
) {
88 p
= const_cast< WCHAR
* >(frontEnd
);
91 while (frontBegin
!= frontEnd
) {
95 for (; backLength
> 0; --backLength
) {
101 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
106 WCHAR
* resolveLink(WCHAR
* path
) {
107 HANDLE h
= CreateFileW(
108 path
, FILE_READ_DATA
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
109 if (h
== INVALID_HANDLE_VALUE
) {
114 BOOL ok
= ReadFile(h
, p1
, MAX_PATH
, &n
, NULL
);
122 for (DWORD i
= 0; i
< n
;) {
123 unsigned char c
= static_cast< unsigned char >(p1
[i
++]);
126 SetLastError(ERROR_BAD_PATHNAME
);
130 if (n2
== MAX_PATH
) {
131 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
140 // Convert from UTF-8 to UTF-16:
143 } else if (c
>= 0xC2 && c
<= 0xDF && i
< n
&&
144 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
145 static_cast< unsigned char >(p1
[i
]) <= 0xBF)
147 p2
[n2
++] = ((c
& 0x1F) << 6) |
148 (static_cast< unsigned char >(p1
[i
++]) & 0x3F);
149 } else if (n
- i
> 1 &&
151 static_cast< unsigned char >(p1
[i
]) >= 0xA0 &&
152 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
153 ((c
>= 0xE1 && c
<= 0xEC || c
>= 0xEE && c
<= 0xEF) &&
154 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
155 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
157 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
158 static_cast< unsigned char >(p1
[i
]) <= 0x9F)) &&
159 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
160 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF)
162 p2
[n2
++] = ((c
& 0x0F) << 12) |
163 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 6) |
164 (static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F);
166 } else if (n
- 2 > 1 &&
168 static_cast< unsigned char >(p1
[i
]) >= 0x90 &&
169 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
170 (c
>= 0xF1 && c
<= 0xF3 &&
171 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
172 static_cast< unsigned char >(p1
[i
]) <= 0xBF) ||
174 static_cast< unsigned char >(p1
[i
]) >= 0x80 &&
175 static_cast< unsigned char >(p1
[i
]) <= 0x8F)) &&
176 static_cast< unsigned char >(p1
[i
+ 1]) >= 0x80 &&
177 static_cast< unsigned char >(p1
[i
+ 1]) <= 0xBF &&
178 static_cast< unsigned char >(p1
[i
+ 2]) >= 0x80 &&
179 static_cast< unsigned char >(p1
[i
+ 2]) <= 0xBF)
181 sal_Int32 u
= ((c
& 0x07) << 18) |
182 ((static_cast< unsigned char >(p1
[i
]) & 0x3F) << 12) |
183 ((static_cast< unsigned char >(p1
[i
+ 1]) & 0x3F) << 6) |
184 (static_cast< unsigned char >(p1
[i
+ 2]) & 0x3F);
186 p2
[n2
++] = static_cast< WCHAR
>(((u
- 0x10000) >> 10) | 0xD800);
187 p2
[n2
++] = static_cast< WCHAR
>(
188 ((u
- 0x10000) & 0x3FF) | 0xDC00);
190 SetLastError(ERROR_BAD_PATHNAME
);
197 if (colon
|| p2
[0] == L
'\\') {
198 // Interpret p2 as an absolute path:
201 // Interpret p2 as a relative path:
202 end
= filename(path
);
204 return buildPath(path
, path
, end
, p2
, n2
);
211 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */