1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "sal/config.h" 29 30 #if defined WNT 31 32 #include <cstddef> 33 34 #define WIN32_LEAN_AND_MEAN 35 #include <windows.h> 36 37 #include "sal/types.h" 38 //#include "tools/pathutils.hxx" 39 40 namespace cli_ure { 41 42 WCHAR * filename(WCHAR * path) { 43 WCHAR * f = path; 44 for (WCHAR * p = path;;) { 45 switch (*p++) { 46 case L'\0': 47 return f; 48 case L'\\': 49 f = p; 50 break; 51 } 52 } 53 } 54 55 WCHAR * buildPath( 56 WCHAR * path, WCHAR const * frontBegin, WCHAR const * frontEnd, 57 WCHAR const * backBegin, std::size_t backLength) 58 { 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'\\')) 65 { 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'\\'))))) 72 { 73 break; 74 } 75 WCHAR const * p = frontEnd - 1; 76 while (p != frontBegin && p[-1] != L'\\') { 77 --p; 78 } 79 if (p == frontBegin) { 80 break; 81 } 82 frontEnd = p; 83 if (backLength == 2) { 84 backBegin += 2; 85 backLength -= 2; 86 } else { 87 backBegin += 3; 88 backLength -= 3; 89 } 90 } 91 if (backLength < 92 static_cast< std::size_t >(MAX_PATH - (frontEnd - frontBegin))) 93 // hopefully std::size_t is large enough 94 { 95 WCHAR * p; 96 if (frontBegin == path) { 97 p = const_cast< WCHAR * >(frontEnd); 98 } else { 99 p = path; 100 while (frontBegin != frontEnd) { 101 *p++ = *frontBegin++; 102 } 103 } 104 for (; backLength > 0; --backLength) { 105 *p++ = *backBegin++; 106 } 107 *p = L'\0'; 108 return p; 109 } else { 110 SetLastError(ERROR_FILENAME_EXCED_RANGE); 111 return NULL; 112 } 113 } 114 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) { 119 return NULL; 120 } 121 char p1[MAX_PATH]; 122 DWORD n; 123 BOOL ok = ReadFile(h, p1, MAX_PATH, &n, NULL); 124 CloseHandle(h); 125 if (!ok) { 126 return NULL; 127 } 128 WCHAR p2[MAX_PATH]; 129 std::size_t n2 = 0; 130 bool colon = false; 131 for (DWORD i = 0; i < n;) { 132 unsigned char c = static_cast< unsigned char >(p1[i++]); 133 switch (c) { 134 case '\0': 135 SetLastError(ERROR_BAD_PATHNAME); 136 return NULL; 137 case '\x0A': 138 case '\x0D': 139 if (n2 == MAX_PATH) { 140 SetLastError(ERROR_FILENAME_EXCED_RANGE); 141 return NULL; 142 } 143 p2[n2] = L'\0'; 144 break; 145 case ':': 146 colon = true; 147 // fall through 148 default: 149 // Convert from UTF-8 to UTF-16: 150 if (c <= 0x7F) { 151 p2[n2++] = c; 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) 155 { 156 p2[n2++] = ((c & 0x1F) << 6) | 157 (static_cast< unsigned char >(p1[i++]) & 0x3F); 158 } else if (n - i > 1 && 159 ((c == 0xE0 && 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) || 165 (c == 0xED && 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) 170 { 171 p2[n2++] = ((c & 0x0F) << 12) | 172 ((static_cast< unsigned char >(p1[i]) & 0x3F) << 6) | 173 (static_cast< unsigned char >(p1[i + 1]) & 0x3F); 174 i += 2; 175 } else if (n - 2 > 1 && 176 ((c == 0xF0 && 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) || 182 (c == 0xF4 && 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) 189 { 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); 194 i += 3; 195 p2[n2++] = static_cast< WCHAR >(((u - 0x10000) >> 10) | 0xD800); 196 p2[n2++] = static_cast< WCHAR >( 197 ((u - 0x10000) & 0x3FF) | 0xDC00); 198 } else { 199 SetLastError(ERROR_BAD_PATHNAME); 200 return NULL; 201 } 202 break; 203 } 204 } 205 WCHAR * end; 206 if (colon || p2[0] == L'\\') { 207 // Interpret p2 as an absolute path: 208 end = path; 209 } else { 210 // Interpret p2 as a relative path: 211 end = filename(path); 212 } 213 return buildPath(path, path, end, p2, n2); 214 } 215 216 } 217 218 #endif 219