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