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