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 #define UNICODE 29*cdf0e10cSrcweir #define _UNICODE 30*cdf0e10cSrcweir #define _WIN32_WINNT_0x0500 31*cdf0e10cSrcweir #include "systools/win32/uwinapi.h" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include "file_url.h" 34*cdf0e10cSrcweir #include "file_error.h" 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include "rtl/alloc.h" 37*cdf0e10cSrcweir #include "osl/diagnose.h" 38*cdf0e10cSrcweir #include "osl/file.h" 39*cdf0e10cSrcweir #include "osl/mutex.h" 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir #include "path_helper.hxx" 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir #include <stdio.h> 44*cdf0e10cSrcweir #include <tchar.h> 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 47*cdf0e10cSrcweir #define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) ) 48*cdf0e10cSrcweir #else 49*cdf0e10cSrcweir #define OSL_ENSURE_FILE( cond, msg, file ) ((void)0) 50*cdf0e10cSrcweir #endif 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir #define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\" 55*cdf0e10cSrcweir #define WSTR_LONG_PATH_PREFIX L"\\\\?\\" 56*cdf0e10cSrcweir #define WSTR_LONG_PATH_PREFIX_UNC L"\\\\?\\UNC\\" 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir //################################################################## 60*cdf0e10cSrcweir // FileURL functions 61*cdf0e10cSrcweir //################################################################## 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir extern "C" oslMutex g_CurrentDirectoryMutex; /* Initialized in dllentry.c */ 64*cdf0e10cSrcweir oslMutex g_CurrentDirectoryMutex = 0; 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir //##################################################### 67*cdf0e10cSrcweir static BOOL IsValidFilePathComponent( 68*cdf0e10cSrcweir LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags) 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir LPCTSTR lpComponentEnd = NULL; 71*cdf0e10cSrcweir LPCTSTR lpCurrent = lpComponent; 72*cdf0e10cSrcweir BOOL fValid = TRUE; /* Assume success */ 73*cdf0e10cSrcweir TCHAR cLast = 0; 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir /* Path component length must not exceed MAX_PATH even if long path with "\\?\" prefix is used */ 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < MAX_PATH ) 78*cdf0e10cSrcweir { 79*cdf0e10cSrcweir switch ( *lpCurrent ) 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir /* Both backslash and slash determine the end of a path component */ 82*cdf0e10cSrcweir case '\0': 83*cdf0e10cSrcweir case '/': 84*cdf0e10cSrcweir case '\\': 85*cdf0e10cSrcweir switch ( cLast ) 86*cdf0e10cSrcweir { 87*cdf0e10cSrcweir /* Component must not end with '.' or blank and can't be empty */ 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir case '.': 90*cdf0e10cSrcweir if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE ) 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir if ( 1 == lpCurrent - lpComponent ) 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir /* Current directory is O.K. */ 95*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 96*cdf0e10cSrcweir break; 97*cdf0e10cSrcweir } 98*cdf0e10cSrcweir else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir /* Parent directory is O.K. */ 101*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 102*cdf0e10cSrcweir break; 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir case 0: 106*cdf0e10cSrcweir case ' ': 107*cdf0e10cSrcweir lpComponentEnd = lpCurrent - 1; 108*cdf0e10cSrcweir fValid = FALSE; 109*cdf0e10cSrcweir break; 110*cdf0e10cSrcweir default: 111*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 112*cdf0e10cSrcweir break; 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir break; 115*cdf0e10cSrcweir /* '?' and '*' are valid wildcards but not valid file name characters */ 116*cdf0e10cSrcweir case '?': 117*cdf0e10cSrcweir case '*': 118*cdf0e10cSrcweir if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS ) 119*cdf0e10cSrcweir break; 120*cdf0e10cSrcweir /* The following characters are reserved */ 121*cdf0e10cSrcweir case '<': 122*cdf0e10cSrcweir case '>': 123*cdf0e10cSrcweir case '\"': 124*cdf0e10cSrcweir case '|': 125*cdf0e10cSrcweir case ':': 126*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 127*cdf0e10cSrcweir fValid = FALSE; 128*cdf0e10cSrcweir break; 129*cdf0e10cSrcweir default: 130*cdf0e10cSrcweir /* Characters below ASCII 32 are not allowed */ 131*cdf0e10cSrcweir if ( *lpCurrent < ' ' ) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 134*cdf0e10cSrcweir fValid = FALSE; 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir break; 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir cLast = *lpCurrent++; 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir /* If we don't reached the end of the component the length of the component was to long 142*cdf0e10cSrcweir ( See condition of while loop ) */ 143*cdf0e10cSrcweir if ( !lpComponentEnd ) 144*cdf0e10cSrcweir { 145*cdf0e10cSrcweir fValid = FALSE; 146*cdf0e10cSrcweir lpComponentEnd = lpCurrent; 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir /* Test wether the component specifies a device name what is not allowed */ 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir // MT: PERFORMANCE: 152*cdf0e10cSrcweir // This is very expensive. A lot of calls to _tcsicmp. 153*cdf0e10cSrcweir // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp! 154*cdf0e10cSrcweir // Possible optimizations 155*cdf0e10cSrcweir // - Array should be const static 156*cdf0e10cSrcweir // - Sorted array, use binary search 157*cdf0e10cSrcweir // - More intelligent check for com1-9, lpt1-9 158*cdf0e10cSrcweir // Maybe make szComponent upper case, don't search case intensitive 159*cdf0e10cSrcweir // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway. 160*cdf0e10cSrcweir /* 161*cdf0e10cSrcweir if ( fValid ) 162*cdf0e10cSrcweir { 163*cdf0e10cSrcweir LPCTSTR alpDeviceNames[] = 164*cdf0e10cSrcweir { 165*cdf0e10cSrcweir TEXT("CON"), 166*cdf0e10cSrcweir TEXT("PRN"), 167*cdf0e10cSrcweir TEXT("AUX"), 168*cdf0e10cSrcweir TEXT("CLOCK$"), 169*cdf0e10cSrcweir TEXT("NUL"), 170*cdf0e10cSrcweir TEXT("LPT1"), 171*cdf0e10cSrcweir TEXT("LPT2"), 172*cdf0e10cSrcweir TEXT("LPT3"), 173*cdf0e10cSrcweir TEXT("LPT4"), 174*cdf0e10cSrcweir TEXT("LPT5"), 175*cdf0e10cSrcweir TEXT("LPT6"), 176*cdf0e10cSrcweir TEXT("LPT7"), 177*cdf0e10cSrcweir TEXT("LPT8"), 178*cdf0e10cSrcweir TEXT("LPT9"), 179*cdf0e10cSrcweir TEXT("COM1"), 180*cdf0e10cSrcweir TEXT("COM2"), 181*cdf0e10cSrcweir TEXT("COM3"), 182*cdf0e10cSrcweir TEXT("COM4"), 183*cdf0e10cSrcweir TEXT("COM5"), 184*cdf0e10cSrcweir TEXT("COM6"), 185*cdf0e10cSrcweir TEXT("COM7"), 186*cdf0e10cSrcweir TEXT("COM8"), 187*cdf0e10cSrcweir TEXT("COM9") 188*cdf0e10cSrcweir }; 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir TCHAR szComponent[MAX_PATH]; 191*cdf0e10cSrcweir int nComponentLength; 192*cdf0e10cSrcweir LPCTSTR lpDot; 193*cdf0e10cSrcweir int i; 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir // A device name with an extension is also invalid 196*cdf0e10cSrcweir lpDot = _tcschr( lpComponent, '.' ); 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir if ( !lpDot || lpDot > lpComponentEnd ) 199*cdf0e10cSrcweir nComponentLength = lpComponentEnd - lpComponent; 200*cdf0e10cSrcweir else 201*cdf0e10cSrcweir nComponentLength = lpDot - lpComponent; 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir _tcsncpy( szComponent, lpComponent, nComponentLength ); 204*cdf0e10cSrcweir szComponent[nComponentLength] = 0; 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ ) 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) ) 209*cdf0e10cSrcweir { 210*cdf0e10cSrcweir lpComponentEnd = lpComponent; 211*cdf0e10cSrcweir fValid = FALSE; 212*cdf0e10cSrcweir break; 213*cdf0e10cSrcweir } 214*cdf0e10cSrcweir } 215*cdf0e10cSrcweir } 216*cdf0e10cSrcweir */ 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir if ( fValid ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir // Empty components are not allowed 221*cdf0e10cSrcweir if ( lpComponentEnd - lpComponent < 1 ) 222*cdf0e10cSrcweir fValid = FALSE; 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir // If we reached the end of the string NULL is returned 225*cdf0e10cSrcweir else if ( !*lpComponentEnd ) 226*cdf0e10cSrcweir lpComponentEnd = NULL; 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir } 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir if ( lppComponentEnd ) 231*cdf0e10cSrcweir *lppComponentEnd = lpComponentEnd; 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir return fValid; 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir //##################################################### 237*cdf0e10cSrcweir #define CHARSET_SEPARATOR TEXT("\\/") 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir DWORD IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_uString **corrected) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir LPCTSTR lpszPath = reinterpret_cast< LPCTSTR >(path->buffer); 242*cdf0e10cSrcweir LPCTSTR lpComponent = lpszPath; 243*cdf0e10cSrcweir BOOL fValid = TRUE; 244*cdf0e10cSrcweir DWORD dwPathType = PATHTYPE_ERROR; 245*cdf0e10cSrcweir sal_Int32 nLength = rtl_uString_getLength( path ); 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) 248*cdf0e10cSrcweir dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE; 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir if ( !lpszPath ) 251*cdf0e10cSrcweir fValid = FALSE; 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir DWORD dwCandidatPathType = PATHTYPE_ERROR; 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1 ) ) 256*cdf0e10cSrcweir { 257*cdf0e10cSrcweir /* This is long path in UNC notation */ 258*cdf0e10cSrcweir lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1; 259*cdf0e10cSrcweir dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC | PATHTYPE_IS_LONGPATH; 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir else if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) ) 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir /* This is long path */ 264*cdf0e10cSrcweir lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1; 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir if ( _istalpha( lpComponent[0] ) && ':' == lpComponent[1] ) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir lpComponent += 2; 269*cdf0e10cSrcweir dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL | PATHTYPE_IS_LONGPATH; 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir } 272*cdf0e10cSrcweir else if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) ) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir /* The UNC path notation */ 275*cdf0e10cSrcweir lpComponent = lpszPath + 2; 276*cdf0e10cSrcweir dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC; 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] ) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir /* Local path verification. Must start with <drive>: */ 281*cdf0e10cSrcweir lpComponent = lpszPath + 2; 282*cdf0e10cSrcweir dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL; 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir 285*cdf0e10cSrcweir if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_UNC ) 286*cdf0e10cSrcweir { 287*cdf0e10cSrcweir fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE ); 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir /* So far we have a valid servername. Now let's see if we also have a network resource */ 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir dwPathType = dwCandidatPathType; 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir if ( fValid ) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir if ( lpComponent && !*++lpComponent ) 296*cdf0e10cSrcweir lpComponent = NULL; 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir if ( !lpComponent ) 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir #if 0 301*cdf0e10cSrcweir /* We only have a Server specification what is invalid */ 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir lpComponent = lpszPath; 304*cdf0e10cSrcweir fValid = FALSE; 305*cdf0e10cSrcweir #else 306*cdf0e10cSrcweir dwPathType |= PATHTYPE_IS_SERVER; 307*cdf0e10cSrcweir #endif 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir else 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir /* Now test the network resource */ 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 ); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir /* If we now reached the end of the path, everything is O.K. */ 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) ) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir lpComponent = NULL; 321*cdf0e10cSrcweir dwPathType |= PATHTYPE_IS_VOLUME; 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir } 324*cdf0e10cSrcweir } 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir else if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_LOCAL ) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) 329*cdf0e10cSrcweir lpComponent++; 330*cdf0e10cSrcweir else if ( *lpComponent ) 331*cdf0e10cSrcweir fValid = FALSE; 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir dwPathType = dwCandidatPathType; 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir /* Now we are behind the backslash or it was a simple drive without backslash */ 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir if ( fValid && !*lpComponent ) 338*cdf0e10cSrcweir { 339*cdf0e10cSrcweir lpComponent = NULL; 340*cdf0e10cSrcweir dwPathType |= PATHTYPE_IS_VOLUME; 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir } 343*cdf0e10cSrcweir else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir /* Can be a relative path */ 346*cdf0e10cSrcweir lpComponent = lpszPath; 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir /* Relative path can start with a backslash */ 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir lpComponent++; 353*cdf0e10cSrcweir if ( !*lpComponent ) 354*cdf0e10cSrcweir lpComponent = NULL; 355*cdf0e10cSrcweir } 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir dwPathType = PATHTYPE_RELATIVE; 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir else 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir /* Anything else is an error */ 362*cdf0e10cSrcweir fValid = FALSE; 363*cdf0e10cSrcweir lpComponent = lpszPath; 364*cdf0e10cSrcweir } 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir /* Now validate each component of the path */ 367*cdf0e10cSrcweir while ( fValid && lpComponent ) 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir // Correct path by merging consecutive slashes: 370*cdf0e10cSrcweir if (*lpComponent == '\\' && corrected != NULL) { 371*cdf0e10cSrcweir sal_Int32 i = lpComponent - lpszPath; 372*cdf0e10cSrcweir rtl_uString_newReplaceStrAt(corrected, path, i, 1, NULL); 373*cdf0e10cSrcweir //TODO: handle out-of-memory 374*cdf0e10cSrcweir lpszPath = reinterpret_cast< LPCTSTR >((*corrected)->buffer); 375*cdf0e10cSrcweir lpComponent = lpszPath + i; 376*cdf0e10cSrcweir } 377*cdf0e10cSrcweir 378*cdf0e10cSrcweir fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags ); 379*cdf0e10cSrcweir 380*cdf0e10cSrcweir if ( fValid && lpComponent ) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir lpComponent++; 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir /* If the string behind the backslash is empty, we've done */ 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir if ( !*lpComponent ) 387*cdf0e10cSrcweir lpComponent = NULL; 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir 391*cdf0e10cSrcweir /* The path can be longer than MAX_PATH only in case it has the longpath prefix */ 392*cdf0e10cSrcweir if ( fValid && !( dwPathType & PATHTYPE_IS_LONGPATH ) && _tcslen( lpszPath ) >= MAX_PATH ) 393*cdf0e10cSrcweir { 394*cdf0e10cSrcweir fValid = FALSE; 395*cdf0e10cSrcweir lpComponent = lpszPath + MAX_PATH; 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir if ( lppError ) 399*cdf0e10cSrcweir *lppError = lpComponent; 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir return fValid ? dwPathType : PATHTYPE_ERROR; 402*cdf0e10cSrcweir } 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir //##################################################### 405*cdf0e10cSrcweir static sal_Int32 PathRemoveFileSpec(LPTSTR lpPath, LPTSTR lpFileName, sal_Int32 nFileBufLen ) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir sal_Int32 nRemoved = 0; 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir if ( nFileBufLen ) 410*cdf0e10cSrcweir { 411*cdf0e10cSrcweir lpFileName[0] = 0; 412*cdf0e10cSrcweir LPTSTR lpLastBkSlash = _tcsrchr( lpPath, '\\' ); 413*cdf0e10cSrcweir LPTSTR lpLastSlash = _tcsrchr( lpPath, '/' ); 414*cdf0e10cSrcweir LPTSTR lpLastDelimiter = lpLastSlash > lpLastBkSlash ? lpLastSlash : lpLastBkSlash; 415*cdf0e10cSrcweir 416*cdf0e10cSrcweir if ( lpLastDelimiter ) 417*cdf0e10cSrcweir { 418*cdf0e10cSrcweir sal_Int32 nDelLen = _tcslen( lpLastDelimiter ); 419*cdf0e10cSrcweir if ( 1 == nDelLen ) 420*cdf0e10cSrcweir { 421*cdf0e10cSrcweir if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' ) 422*cdf0e10cSrcweir { 423*cdf0e10cSrcweir *lpLastDelimiter = 0; 424*cdf0e10cSrcweir *lpFileName = 0; 425*cdf0e10cSrcweir nRemoved = nDelLen; 426*cdf0e10cSrcweir } 427*cdf0e10cSrcweir } 428*cdf0e10cSrcweir else if ( nDelLen && nDelLen - 1 < nFileBufLen ) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir _tcscpy( lpFileName, lpLastDelimiter + 1 ); 431*cdf0e10cSrcweir *(++lpLastDelimiter) = 0; 432*cdf0e10cSrcweir nRemoved = nDelLen - 1; 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir } 435*cdf0e10cSrcweir } 436*cdf0e10cSrcweir 437*cdf0e10cSrcweir return nRemoved; 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir //##################################################### 441*cdf0e10cSrcweir // Undocumented in SHELL32.DLL ordinal 32 442*cdf0e10cSrcweir static LPTSTR PathAddBackslash(LPTSTR lpPath, sal_Int32 nBufLen) 443*cdf0e10cSrcweir { 444*cdf0e10cSrcweir LPTSTR lpEndPath = NULL; 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir if ( lpPath ) 447*cdf0e10cSrcweir { 448*cdf0e10cSrcweir int nLen = _tcslen(lpPath); 449*cdf0e10cSrcweir 450*cdf0e10cSrcweir if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < nBufLen - 1 ) 451*cdf0e10cSrcweir { 452*cdf0e10cSrcweir lpEndPath = lpPath + nLen; 453*cdf0e10cSrcweir *lpEndPath++ = '\\'; 454*cdf0e10cSrcweir *lpEndPath = 0; 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir } 457*cdf0e10cSrcweir return lpEndPath; 458*cdf0e10cSrcweir } 459*cdf0e10cSrcweir 460*cdf0e10cSrcweir //##################################################### 461*cdf0e10cSrcweir // Same as GetLongPathName but also 95/NT4 462*cdf0e10cSrcweir static DWORD GetCaseCorrectPathNameEx( 463*cdf0e10cSrcweir LPTSTR lpszPath, // path buffer to convert 464*cdf0e10cSrcweir DWORD cchBuffer, // size of path buffer 465*cdf0e10cSrcweir DWORD nSkipLevels, 466*cdf0e10cSrcweir BOOL bCheckExistence ) 467*cdf0e10cSrcweir { 468*cdf0e10cSrcweir ::osl::LongPathBuffer< WCHAR > szFile( MAX_PATH + 1 ); 469*cdf0e10cSrcweir sal_Int32 nRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 ); 470*cdf0e10cSrcweir sal_Int32 nLastStepRemoved = nRemoved; 471*cdf0e10cSrcweir while ( nLastStepRemoved && szFile[0] == 0 ) 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir // remove separators 474*cdf0e10cSrcweir nLastStepRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 ); 475*cdf0e10cSrcweir nRemoved += nLastStepRemoved; 476*cdf0e10cSrcweir } 477*cdf0e10cSrcweir 478*cdf0e10cSrcweir if ( nRemoved ) 479*cdf0e10cSrcweir { 480*cdf0e10cSrcweir BOOL bSkipThis = FALSE; 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir if ( 0 == _tcscmp( szFile, TEXT("..") ) ) 483*cdf0e10cSrcweir { 484*cdf0e10cSrcweir bSkipThis = TRUE; 485*cdf0e10cSrcweir nSkipLevels += 1; 486*cdf0e10cSrcweir } 487*cdf0e10cSrcweir else if ( 0 == _tcscmp( szFile, TEXT(".") ) ) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir bSkipThis = TRUE; 490*cdf0e10cSrcweir } 491*cdf0e10cSrcweir else if ( nSkipLevels ) 492*cdf0e10cSrcweir { 493*cdf0e10cSrcweir bSkipThis = TRUE; 494*cdf0e10cSrcweir nSkipLevels--; 495*cdf0e10cSrcweir } 496*cdf0e10cSrcweir else 497*cdf0e10cSrcweir bSkipThis = FALSE; 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir GetCaseCorrectPathNameEx( lpszPath, cchBuffer, nSkipLevels, bCheckExistence ); 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir PathAddBackslash( lpszPath, cchBuffer ); 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir /* Analyze parent if not only a trailing backslash was cutted but a real file spec */ 504*cdf0e10cSrcweir if ( !bSkipThis ) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir if ( bCheckExistence ) 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir ::osl::LongPathBuffer< WCHAR > aShortPath( MAX_LONG_PATH ); 509*cdf0e10cSrcweir _tcscpy( aShortPath, lpszPath ); 510*cdf0e10cSrcweir _tcscat( aShortPath, szFile ); 511*cdf0e10cSrcweir 512*cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData; 513*cdf0e10cSrcweir HANDLE hFind = FindFirstFile( aShortPath, &aFindFileData ); 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir if ( IsValidHandle(hFind) ) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir _tcscat( lpszPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName ); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir FindClose( hFind ); 520*cdf0e10cSrcweir } 521*cdf0e10cSrcweir else 522*cdf0e10cSrcweir lpszPath[0] = 0; 523*cdf0e10cSrcweir } 524*cdf0e10cSrcweir else 525*cdf0e10cSrcweir { 526*cdf0e10cSrcweir /* add the segment name back */ 527*cdf0e10cSrcweir _tcscat( lpszPath, szFile ); 528*cdf0e10cSrcweir } 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir } 531*cdf0e10cSrcweir else 532*cdf0e10cSrcweir { 533*cdf0e10cSrcweir /* File specification can't be removed therefore the short path is either a drive 534*cdf0e10cSrcweir or a network share. If still levels to skip are left, the path specification 535*cdf0e10cSrcweir tries to travel below the file system root */ 536*cdf0e10cSrcweir if ( nSkipLevels ) 537*cdf0e10cSrcweir lpszPath[0] = 0; 538*cdf0e10cSrcweir else 539*cdf0e10cSrcweir _tcsupr( lpszPath ); 540*cdf0e10cSrcweir } 541*cdf0e10cSrcweir 542*cdf0e10cSrcweir return _tcslen( lpszPath ); 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir 545*cdf0e10cSrcweir //##################################################### 546*cdf0e10cSrcweir #define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\" 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir DWORD GetCaseCorrectPathName( 549*cdf0e10cSrcweir LPCTSTR lpszShortPath, // file name 550*cdf0e10cSrcweir LPTSTR lpszLongPath, // path buffer 551*cdf0e10cSrcweir DWORD cchBuffer, // size of path buffer 552*cdf0e10cSrcweir BOOL bCheckExistence 553*cdf0e10cSrcweir ) 554*cdf0e10cSrcweir { 555*cdf0e10cSrcweir /* Special handling for "\\.\" as system root */ 556*cdf0e10cSrcweir if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) ) 557*cdf0e10cSrcweir { 558*cdf0e10cSrcweir if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) ) 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH ); 561*cdf0e10cSrcweir return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1; 562*cdf0e10cSrcweir } 563*cdf0e10cSrcweir else 564*cdf0e10cSrcweir { 565*cdf0e10cSrcweir return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1; 566*cdf0e10cSrcweir } 567*cdf0e10cSrcweir } 568*cdf0e10cSrcweir else if ( lpszShortPath ) 569*cdf0e10cSrcweir { 570*cdf0e10cSrcweir if ( _tcslen( lpszShortPath ) <= cchBuffer ) 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir _tcscpy( lpszLongPath, lpszShortPath ); 573*cdf0e10cSrcweir return GetCaseCorrectPathNameEx( lpszLongPath, cchBuffer, 0, bCheckExistence ); 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir } 576*cdf0e10cSrcweir 577*cdf0e10cSrcweir return 0; 578*cdf0e10cSrcweir } 579*cdf0e10cSrcweir 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir //############################################# 582*cdf0e10cSrcweir static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL ) 583*cdf0e10cSrcweir { 584*cdf0e10cSrcweir sal_Char *pBuffer; 585*cdf0e10cSrcweir const sal_Char *pSrcEnd; 586*cdf0e10cSrcweir const sal_Char *pSrc; 587*cdf0e10cSrcweir sal_Char *pDest; 588*cdf0e10cSrcweir sal_Int32 nSrcLen; 589*cdf0e10cSrcweir sal_Bool bValidEncoded = sal_True; /* Assume success */ 590*cdf0e10cSrcweir 591*cdf0e10cSrcweir /* The resulting decoded string length is shorter or equal to the source length */ 592*cdf0e10cSrcweir 593*cdf0e10cSrcweir nSrcLen = rtl_string_getLength(strUTF8); 594*cdf0e10cSrcweir pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1)); 595*cdf0e10cSrcweir 596*cdf0e10cSrcweir pDest = pBuffer; 597*cdf0e10cSrcweir pSrc = rtl_string_getStr(strUTF8); 598*cdf0e10cSrcweir pSrcEnd = pSrc + nSrcLen; 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir /* Now decode the URL what should result in an UTF8 string */ 601*cdf0e10cSrcweir while ( bValidEncoded && pSrc < pSrcEnd ) 602*cdf0e10cSrcweir { 603*cdf0e10cSrcweir switch ( *pSrc ) 604*cdf0e10cSrcweir { 605*cdf0e10cSrcweir case '%': 606*cdf0e10cSrcweir { 607*cdf0e10cSrcweir sal_Char aToken[3]; 608*cdf0e10cSrcweir sal_Char aChar; 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir pSrc++; 611*cdf0e10cSrcweir aToken[0] = *pSrc++; 612*cdf0e10cSrcweir aToken[1] = *pSrc++; 613*cdf0e10cSrcweir aToken[2] = 0; 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir aChar = (sal_Char)strtoul( aToken, NULL, 16 ); 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir /* The chars are path delimiters and must not be encoded */ 618*cdf0e10cSrcweir 619*cdf0e10cSrcweir if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar ) 620*cdf0e10cSrcweir bValidEncoded = sal_False; 621*cdf0e10cSrcweir else 622*cdf0e10cSrcweir *pDest++ = aChar; 623*cdf0e10cSrcweir } 624*cdf0e10cSrcweir break; 625*cdf0e10cSrcweir default: 626*cdf0e10cSrcweir *pDest++ = *pSrc++; 627*cdf0e10cSrcweir break; 628*cdf0e10cSrcweir } 629*cdf0e10cSrcweir } 630*cdf0e10cSrcweir 631*cdf0e10cSrcweir *pDest++ = 0; 632*cdf0e10cSrcweir 633*cdf0e10cSrcweir if ( bValidEncoded ) 634*cdf0e10cSrcweir { 635*cdf0e10cSrcweir rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 636*cdf0e10cSrcweir OSL_ASSERT(*pstrDecodedURL != 0); 637*cdf0e10cSrcweir } 638*cdf0e10cSrcweir 639*cdf0e10cSrcweir rtl_freeMemory( pBuffer ); 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir return bValidEncoded; 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir 644*cdf0e10cSrcweir //############################################# 645*cdf0e10cSrcweir static void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL ) 646*cdf0e10cSrcweir { 647*cdf0e10cSrcweir /* Encode non ascii characters within the URL */ 648*cdf0e10cSrcweir 649*cdf0e10cSrcweir rtl_String *strUTF8 = NULL; 650*cdf0e10cSrcweir sal_Char *pszEncodedURL; 651*cdf0e10cSrcweir const sal_Char *pURLScan; 652*cdf0e10cSrcweir sal_Char *pURLDest; 653*cdf0e10cSrcweir sal_Int32 nURLScanLen; 654*cdf0e10cSrcweir sal_Int32 nURLScanCount; 655*cdf0e10cSrcweir 656*cdf0e10cSrcweir rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 657*cdf0e10cSrcweir 658*cdf0e10cSrcweir pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) ); 659*cdf0e10cSrcweir 660*cdf0e10cSrcweir pURLDest = pszEncodedURL; 661*cdf0e10cSrcweir pURLScan = rtl_string_getStr( strUTF8 ); 662*cdf0e10cSrcweir nURLScanLen = rtl_string_getLength( strUTF8 ); 663*cdf0e10cSrcweir nURLScanCount = 0; 664*cdf0e10cSrcweir 665*cdf0e10cSrcweir while ( nURLScanCount < nURLScanLen ) 666*cdf0e10cSrcweir { 667*cdf0e10cSrcweir sal_Char cCurrent = *pURLScan; 668*cdf0e10cSrcweir switch ( cCurrent ) 669*cdf0e10cSrcweir { 670*cdf0e10cSrcweir default: 671*cdf0e10cSrcweir if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) ) 672*cdf0e10cSrcweir { 673*cdf0e10cSrcweir sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent ); 674*cdf0e10cSrcweir pURLDest += 3; 675*cdf0e10cSrcweir break; 676*cdf0e10cSrcweir } 677*cdf0e10cSrcweir case '!': 678*cdf0e10cSrcweir case '\'': 679*cdf0e10cSrcweir case '(': 680*cdf0e10cSrcweir case ')': 681*cdf0e10cSrcweir case '*': 682*cdf0e10cSrcweir case '-': 683*cdf0e10cSrcweir case '.': 684*cdf0e10cSrcweir case '_': 685*cdf0e10cSrcweir case '~': 686*cdf0e10cSrcweir case '$': 687*cdf0e10cSrcweir case '&': 688*cdf0e10cSrcweir case '+': 689*cdf0e10cSrcweir case ',': 690*cdf0e10cSrcweir case '=': 691*cdf0e10cSrcweir case '@': 692*cdf0e10cSrcweir case ':': 693*cdf0e10cSrcweir case '/': 694*cdf0e10cSrcweir case '\\': 695*cdf0e10cSrcweir case '|': 696*cdf0e10cSrcweir *pURLDest++ = cCurrent; 697*cdf0e10cSrcweir break; 698*cdf0e10cSrcweir case 0: 699*cdf0e10cSrcweir break; 700*cdf0e10cSrcweir } 701*cdf0e10cSrcweir 702*cdf0e10cSrcweir pURLScan++; 703*cdf0e10cSrcweir nURLScanCount++; 704*cdf0e10cSrcweir } 705*cdf0e10cSrcweir 706*cdf0e10cSrcweir *pURLDest = 0; 707*cdf0e10cSrcweir 708*cdf0e10cSrcweir rtl_string_release( strUTF8 ); 709*cdf0e10cSrcweir rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL ); 710*cdf0e10cSrcweir rtl_freeMemory( pszEncodedURL ); 711*cdf0e10cSrcweir } 712*cdf0e10cSrcweir 713*cdf0e10cSrcweir //############################################# 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir oslFileError _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative ) 716*cdf0e10cSrcweir { 717*cdf0e10cSrcweir rtl_String *strUTF8 = NULL; 718*cdf0e10cSrcweir rtl_uString *strDecodedURL = NULL; 719*cdf0e10cSrcweir rtl_uString *strTempPath = NULL; 720*cdf0e10cSrcweir const sal_Unicode *pDecodedURL; 721*cdf0e10cSrcweir sal_uInt32 nDecodedLen; 722*cdf0e10cSrcweir sal_Bool bValidEncoded; 723*cdf0e10cSrcweir oslFileError nError = osl_File_E_INVAL; /* Assume failure */ 724*cdf0e10cSrcweir 725*cdf0e10cSrcweir /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from 726*cdf0e10cSrcweir having a mixed encoded URL later */ 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */ 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir OSL_ENSURE_FILE( 733*cdf0e10cSrcweir strUTF8->length == strURL->length || 734*cdf0e10cSrcweir 0 != rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 ) 735*cdf0e10cSrcweir ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL ); 736*cdf0e10cSrcweir 737*cdf0e10cSrcweir bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL ); 738*cdf0e10cSrcweir 739*cdf0e10cSrcweir /* Release the encoded UTF8 string */ 740*cdf0e10cSrcweir rtl_string_release( strUTF8 ); 741*cdf0e10cSrcweir 742*cdf0e10cSrcweir if ( bValidEncoded ) 743*cdf0e10cSrcweir { 744*cdf0e10cSrcweir /* Replace backslashes and pipes */ 745*cdf0e10cSrcweir 746*cdf0e10cSrcweir rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' ); 747*cdf0e10cSrcweir rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' ); 748*cdf0e10cSrcweir 749*cdf0e10cSrcweir pDecodedURL = rtl_uString_getStr( strDecodedURL ); 750*cdf0e10cSrcweir nDecodedLen = rtl_uString_getLength( strDecodedURL ); 751*cdf0e10cSrcweir 752*cdf0e10cSrcweir /* Must start with "file://" */ 753*cdf0e10cSrcweir if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) ) 754*cdf0e10cSrcweir { 755*cdf0e10cSrcweir sal_uInt32 nSkip; 756*cdf0e10cSrcweir 757*cdf0e10cSrcweir if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) ) 758*cdf0e10cSrcweir nSkip = 8; 759*cdf0e10cSrcweir else if ( 760*cdf0e10cSrcweir 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) || 761*cdf0e10cSrcweir 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 ) 762*cdf0e10cSrcweir ) 763*cdf0e10cSrcweir nSkip = 17; 764*cdf0e10cSrcweir else 765*cdf0e10cSrcweir nSkip = 5; 766*cdf0e10cSrcweir 767*cdf0e10cSrcweir /* Indicates local root */ 768*cdf0e10cSrcweir if ( nDecodedLen == nSkip ) 769*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strTempPath, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 ); 770*cdf0e10cSrcweir else 771*cdf0e10cSrcweir { 772*cdf0e10cSrcweir /* do not separate the directory and file case, so the maximal path lengs without prefix is MAX_PATH-12 */ 773*cdf0e10cSrcweir if ( nDecodedLen - nSkip <= MAX_PATH - 12 ) 774*cdf0e10cSrcweir { 775*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip ); 776*cdf0e10cSrcweir } 777*cdf0e10cSrcweir else 778*cdf0e10cSrcweir { 779*cdf0e10cSrcweir ::osl::LongPathBuffer< sal_Unicode > aBuf( MAX_LONG_PATH ); 780*cdf0e10cSrcweir sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>(pDecodedURL + nSkip), 781*cdf0e10cSrcweir ::osl::mingw_reinterpret_cast<LPTSTR>(aBuf), 782*cdf0e10cSrcweir aBuf.getBufSizeInSymbols(), 783*cdf0e10cSrcweir sal_False ); 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir if ( nNewLen <= MAX_PATH - 12 786*cdf0e10cSrcweir || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 ) 787*cdf0e10cSrcweir || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) ) 788*cdf0e10cSrcweir { 789*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strTempPath, aBuf, nNewLen ); 790*cdf0e10cSrcweir } 791*cdf0e10cSrcweir else if ( pDecodedURL[nSkip] == (sal_Unicode)'\\' && pDecodedURL[nSkip+1] == (sal_Unicode)'\\' ) 792*cdf0e10cSrcweir { 793*cdf0e10cSrcweir /* it should be an UNC path, use the according prefix */ 794*cdf0e10cSrcweir rtl_uString *strSuffix = NULL; 795*cdf0e10cSrcweir rtl_uString *strPrefix = NULL; 796*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1 ); 797*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strSuffix, aBuf + 2, nNewLen - 2 ); 798*cdf0e10cSrcweir 799*cdf0e10cSrcweir rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix ); 800*cdf0e10cSrcweir 801*cdf0e10cSrcweir rtl_uString_release( strPrefix ); 802*cdf0e10cSrcweir rtl_uString_release( strSuffix ); 803*cdf0e10cSrcweir } 804*cdf0e10cSrcweir else 805*cdf0e10cSrcweir { 806*cdf0e10cSrcweir rtl_uString *strSuffix = NULL; 807*cdf0e10cSrcweir rtl_uString *strPrefix = NULL; 808*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1 ); 809*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strSuffix, aBuf, nNewLen ); 810*cdf0e10cSrcweir 811*cdf0e10cSrcweir rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix ); 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir rtl_uString_release( strPrefix ); 814*cdf0e10cSrcweir rtl_uString_release( strSuffix ); 815*cdf0e10cSrcweir } 816*cdf0e10cSrcweir } 817*cdf0e10cSrcweir } 818*cdf0e10cSrcweir 819*cdf0e10cSrcweir if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) ) 820*cdf0e10cSrcweir nError = osl_File_E_None; 821*cdf0e10cSrcweir } 822*cdf0e10cSrcweir else if ( bAllowRelative ) /* This maybe a relative file URL */ 823*cdf0e10cSrcweir { 824*cdf0e10cSrcweir /* In future the relative path could be converted to absolute if it is too long */ 825*cdf0e10cSrcweir rtl_uString_assign( &strTempPath, strDecodedURL ); 826*cdf0e10cSrcweir 827*cdf0e10cSrcweir if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) ) 828*cdf0e10cSrcweir nError = osl_File_E_None; 829*cdf0e10cSrcweir } 830*cdf0e10cSrcweir /* 831*cdf0e10cSrcweir else 832*cdf0e10cSrcweir OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL ); 833*cdf0e10cSrcweir */ 834*cdf0e10cSrcweir 835*cdf0e10cSrcweir } 836*cdf0e10cSrcweir 837*cdf0e10cSrcweir if ( strDecodedURL ) 838*cdf0e10cSrcweir rtl_uString_release( strDecodedURL ); 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir if ( osl_File_E_None == nError ) 841*cdf0e10cSrcweir rtl_uString_assign( pustrPath, strTempPath ); 842*cdf0e10cSrcweir 843*cdf0e10cSrcweir if ( strTempPath ) 844*cdf0e10cSrcweir rtl_uString_release( strTempPath ); 845*cdf0e10cSrcweir 846*cdf0e10cSrcweir /* 847*cdf0e10cSrcweir OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL ); 848*cdf0e10cSrcweir */ 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir return nError; 851*cdf0e10cSrcweir } 852*cdf0e10cSrcweir 853*cdf0e10cSrcweir //############################################# 854*cdf0e10cSrcweir oslFileError _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL ) 855*cdf0e10cSrcweir { 856*cdf0e10cSrcweir oslFileError nError = osl_File_E_INVAL; /* Assume failure */ 857*cdf0e10cSrcweir rtl_uString *strTempURL = NULL; 858*cdf0e10cSrcweir DWORD dwPathType = PATHTYPE_ERROR; 859*cdf0e10cSrcweir 860*cdf0e10cSrcweir if (strPath) 861*cdf0e10cSrcweir dwPathType = IsValidFilePath(strPath, NULL, VALIDATEPATH_ALLOW_RELATIVE, NULL); 862*cdf0e10cSrcweir 863*cdf0e10cSrcweir if (dwPathType) 864*cdf0e10cSrcweir { 865*cdf0e10cSrcweir rtl_uString *strTempPath = NULL; 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir if ( dwPathType & PATHTYPE_IS_LONGPATH ) 868*cdf0e10cSrcweir { 869*cdf0e10cSrcweir rtl_uString *strBuffer = NULL; 870*cdf0e10cSrcweir sal_uInt32 nIgnore = 0; 871*cdf0e10cSrcweir sal_uInt32 nLength = 0; 872*cdf0e10cSrcweir 873*cdf0e10cSrcweir /* the path has the longpath prefix, lets remove it */ 874*cdf0e10cSrcweir switch ( dwPathType & PATHTYPE_MASK_TYPE ) 875*cdf0e10cSrcweir { 876*cdf0e10cSrcweir case PATHTYPE_ABSOLUTE_UNC: 877*cdf0e10cSrcweir nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1; 878*cdf0e10cSrcweir OSL_ENSURE( nIgnore == 8, "Unexpected long path UNC prefix!" ); 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir /* generate the normal UNC path */ 881*cdf0e10cSrcweir nLength = rtl_uString_getLength( strPath ); 882*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore - 2, nLength - nIgnore + 2 ); 883*cdf0e10cSrcweir strBuffer->buffer[0] = '\\'; 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' ); 886*cdf0e10cSrcweir rtl_uString_release( strBuffer ); 887*cdf0e10cSrcweir break; 888*cdf0e10cSrcweir 889*cdf0e10cSrcweir case PATHTYPE_ABSOLUTE_LOCAL: 890*cdf0e10cSrcweir nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1; 891*cdf0e10cSrcweir OSL_ENSURE( nIgnore == 4, "Unexpected long path prefix!" ); 892*cdf0e10cSrcweir 893*cdf0e10cSrcweir /* generate the normal path */ 894*cdf0e10cSrcweir nLength = rtl_uString_getLength( strPath ); 895*cdf0e10cSrcweir rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore, nLength - nIgnore ); 896*cdf0e10cSrcweir 897*cdf0e10cSrcweir rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' ); 898*cdf0e10cSrcweir rtl_uString_release( strBuffer ); 899*cdf0e10cSrcweir break; 900*cdf0e10cSrcweir 901*cdf0e10cSrcweir default: 902*cdf0e10cSrcweir OSL_ASSERT( "Unexpected long path format!" ); 903*cdf0e10cSrcweir rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' ); 904*cdf0e10cSrcweir break; 905*cdf0e10cSrcweir } 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir else 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir /* Replace backslashes */ 910*cdf0e10cSrcweir rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' ); 911*cdf0e10cSrcweir } 912*cdf0e10cSrcweir 913*cdf0e10cSrcweir switch ( dwPathType & PATHTYPE_MASK_TYPE ) 914*cdf0e10cSrcweir { 915*cdf0e10cSrcweir case PATHTYPE_RELATIVE: 916*cdf0e10cSrcweir rtl_uString_assign( &strTempURL, strTempPath ); 917*cdf0e10cSrcweir nError = osl_File_E_None; 918*cdf0e10cSrcweir break; 919*cdf0e10cSrcweir case PATHTYPE_ABSOLUTE_UNC: 920*cdf0e10cSrcweir rtl_uString_newFromAscii( &strTempURL, "file:" ); 921*cdf0e10cSrcweir rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); 922*cdf0e10cSrcweir nError = osl_File_E_None; 923*cdf0e10cSrcweir break; 924*cdf0e10cSrcweir case PATHTYPE_ABSOLUTE_LOCAL: 925*cdf0e10cSrcweir rtl_uString_newFromAscii( &strTempURL, "file:///" ); 926*cdf0e10cSrcweir rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); 927*cdf0e10cSrcweir nError = osl_File_E_None; 928*cdf0e10cSrcweir break; 929*cdf0e10cSrcweir default: 930*cdf0e10cSrcweir break; 931*cdf0e10cSrcweir } 932*cdf0e10cSrcweir 933*cdf0e10cSrcweir /* Release temp path */ 934*cdf0e10cSrcweir rtl_uString_release( strTempPath ); 935*cdf0e10cSrcweir } 936*cdf0e10cSrcweir 937*cdf0e10cSrcweir if ( osl_File_E_None == nError ) 938*cdf0e10cSrcweir { 939*cdf0e10cSrcweir rtl_String *strEncodedURL = NULL; 940*cdf0e10cSrcweir 941*cdf0e10cSrcweir /* Encode the URL */ 942*cdf0e10cSrcweir _osl_encodeURL( strTempURL, &strEncodedURL ); 943*cdf0e10cSrcweir 944*cdf0e10cSrcweir /* Provide URL via unicode string */ 945*cdf0e10cSrcweir rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); 946*cdf0e10cSrcweir OSL_ASSERT(*pstrURL != 0); 947*cdf0e10cSrcweir rtl_string_release( strEncodedURL ); 948*cdf0e10cSrcweir } 949*cdf0e10cSrcweir 950*cdf0e10cSrcweir /* Release temp URL */ 951*cdf0e10cSrcweir if ( strTempURL ) 952*cdf0e10cSrcweir rtl_uString_release( strTempURL ); 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir /* 955*cdf0e10cSrcweir OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath ); 956*cdf0e10cSrcweir */ 957*cdf0e10cSrcweir return nError; 958*cdf0e10cSrcweir } 959*cdf0e10cSrcweir 960*cdf0e10cSrcweir //##################################################### 961*cdf0e10cSrcweir oslFileError SAL_CALL osl_getFileURLFromSystemPath( 962*cdf0e10cSrcweir rtl_uString* ustrPath, rtl_uString** pustrURL ) 963*cdf0e10cSrcweir { 964*cdf0e10cSrcweir return _osl_getFileURLFromSystemPath( ustrPath, pustrURL ); 965*cdf0e10cSrcweir } 966*cdf0e10cSrcweir 967*cdf0e10cSrcweir //##################################################### 968*cdf0e10cSrcweir oslFileError SAL_CALL osl_getSystemPathFromFileURL( 969*cdf0e10cSrcweir rtl_uString *ustrURL, rtl_uString **pustrPath) 970*cdf0e10cSrcweir { 971*cdf0e10cSrcweir return _osl_getSystemPathFromFileURL( ustrURL, pustrPath, sal_True ); 972*cdf0e10cSrcweir } 973*cdf0e10cSrcweir 974*cdf0e10cSrcweir //##################################################### 975*cdf0e10cSrcweir oslFileError SAL_CALL osl_searchFileURL( 976*cdf0e10cSrcweir rtl_uString *ustrFileName, 977*cdf0e10cSrcweir rtl_uString *ustrSystemSearchPath, 978*cdf0e10cSrcweir rtl_uString **pustrPath) 979*cdf0e10cSrcweir { 980*cdf0e10cSrcweir rtl_uString *ustrUNCPath = NULL; 981*cdf0e10cSrcweir rtl_uString *ustrSysPath = NULL; 982*cdf0e10cSrcweir oslFileError error; 983*cdf0e10cSrcweir 984*cdf0e10cSrcweir /* First try to interpret the file name as an URL even a relative one */ 985*cdf0e10cSrcweir error = _osl_getSystemPathFromFileURL( ustrFileName, &ustrUNCPath, sal_True ); 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir /* So far we either have an UNC path or something invalid 988*cdf0e10cSrcweir Now create a system path */ 989*cdf0e10cSrcweir if ( osl_File_E_None == error ) 990*cdf0e10cSrcweir error = _osl_getSystemPathFromFileURL( ustrUNCPath, &ustrSysPath, sal_True ); 991*cdf0e10cSrcweir 992*cdf0e10cSrcweir if ( osl_File_E_None == error ) 993*cdf0e10cSrcweir { 994*cdf0e10cSrcweir DWORD nBufferLength; 995*cdf0e10cSrcweir DWORD dwResult; 996*cdf0e10cSrcweir LPTSTR lpBuffer = NULL; 997*cdf0e10cSrcweir LPTSTR lpszFilePart; 998*cdf0e10cSrcweir 999*cdf0e10cSrcweir /* Repeat calling SearchPath ... 1000*cdf0e10cSrcweir Start with MAX_PATH for the buffer. In most cases this 1001*cdf0e10cSrcweir will be enough and does not force the loop to runtwice */ 1002*cdf0e10cSrcweir dwResult = MAX_PATH; 1003*cdf0e10cSrcweir 1004*cdf0e10cSrcweir do 1005*cdf0e10cSrcweir { 1006*cdf0e10cSrcweir /* If search path is empty use a NULL pointer instead according to MSDN documentation of SearchPath */ 1007*cdf0e10cSrcweir LPCTSTR lpszSearchPath = ustrSystemSearchPath && ustrSystemSearchPath->length ? reinterpret_cast<LPCTSTR>(ustrSystemSearchPath->buffer) : NULL; 1008*cdf0e10cSrcweir LPCTSTR lpszSearchFile = reinterpret_cast<LPCTSTR>(ustrSysPath->buffer); 1009*cdf0e10cSrcweir 1010*cdf0e10cSrcweir /* Allocate space for buffer according to previous returned count of required chars */ 1011*cdf0e10cSrcweir /* +1 is not neccessary if we follow MSDN documentation but for robustness we do so */ 1012*cdf0e10cSrcweir nBufferLength = dwResult + 1; 1013*cdf0e10cSrcweir lpBuffer = lpBuffer ? 1014*cdf0e10cSrcweir reinterpret_cast<LPTSTR>(rtl_reallocateMemory(lpBuffer, nBufferLength * sizeof(TCHAR))) : 1015*cdf0e10cSrcweir reinterpret_cast<LPTSTR>(rtl_allocateMemory(nBufferLength * sizeof(TCHAR))); 1016*cdf0e10cSrcweir 1017*cdf0e10cSrcweir dwResult = SearchPath( lpszSearchPath, lpszSearchFile, NULL, nBufferLength, lpBuffer, &lpszFilePart ); 1018*cdf0e10cSrcweir } while ( dwResult && dwResult >= nBufferLength ); 1019*cdf0e10cSrcweir 1020*cdf0e10cSrcweir /* ... until an error occures or buffer is large enough. 1021*cdf0e10cSrcweir dwResult == nBufferLength can not happen according to documentation but lets be robust ;-) */ 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir if ( dwResult ) 1024*cdf0e10cSrcweir { 1025*cdf0e10cSrcweir rtl_uString_newFromStr( &ustrSysPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) ); 1026*cdf0e10cSrcweir error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath ); 1027*cdf0e10cSrcweir } 1028*cdf0e10cSrcweir else 1029*cdf0e10cSrcweir { 1030*cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData; 1031*cdf0e10cSrcweir HANDLE hFind; 1032*cdf0e10cSrcweir 1033*cdf0e10cSrcweir /* Somthing went wrong, perhaps the path was absolute */ 1034*cdf0e10cSrcweir error = oslTranslateFileError( GetLastError() ); 1035*cdf0e10cSrcweir 1036*cdf0e10cSrcweir hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(ustrSysPath->buffer), &aFindFileData ); 1037*cdf0e10cSrcweir 1038*cdf0e10cSrcweir if ( IsValidHandle(hFind) ) 1039*cdf0e10cSrcweir { 1040*cdf0e10cSrcweir error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath ); 1041*cdf0e10cSrcweir FindClose( hFind ); 1042*cdf0e10cSrcweir } 1043*cdf0e10cSrcweir } 1044*cdf0e10cSrcweir 1045*cdf0e10cSrcweir rtl_freeMemory( lpBuffer ); 1046*cdf0e10cSrcweir } 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir if ( ustrSysPath ) 1049*cdf0e10cSrcweir rtl_uString_release( ustrSysPath ); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir if ( ustrUNCPath ) 1052*cdf0e10cSrcweir rtl_uString_release( ustrUNCPath ); 1053*cdf0e10cSrcweir 1054*cdf0e10cSrcweir return error; 1055*cdf0e10cSrcweir } 1056*cdf0e10cSrcweir 1057*cdf0e10cSrcweir //##################################################### 1058*cdf0e10cSrcweir 1059*cdf0e10cSrcweir oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL ) 1060*cdf0e10cSrcweir { 1061*cdf0e10cSrcweir oslFileError eError; 1062*cdf0e10cSrcweir rtl_uString *ustrRelSysPath = NULL; 1063*cdf0e10cSrcweir rtl_uString *ustrBaseSysPath = NULL; 1064*cdf0e10cSrcweir 1065*cdf0e10cSrcweir if ( ustrBaseURL && ustrBaseURL->length ) 1066*cdf0e10cSrcweir { 1067*cdf0e10cSrcweir eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False ); 1068*cdf0e10cSrcweir OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" ); 1069*cdf0e10cSrcweir 1070*cdf0e10cSrcweir eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True ); 1071*cdf0e10cSrcweir } 1072*cdf0e10cSrcweir else 1073*cdf0e10cSrcweir { 1074*cdf0e10cSrcweir eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False ); 1075*cdf0e10cSrcweir OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" ); 1076*cdf0e10cSrcweir } 1077*cdf0e10cSrcweir 1078*cdf0e10cSrcweir if ( !eError ) 1079*cdf0e10cSrcweir { 1080*cdf0e10cSrcweir ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH ); 1081*cdf0e10cSrcweir ::osl::LongPathBuffer< sal_Unicode > aCurrentDir( MAX_LONG_PATH ); 1082*cdf0e10cSrcweir LPTSTR lpFilePart = NULL; 1083*cdf0e10cSrcweir DWORD dwResult; 1084*cdf0e10cSrcweir 1085*cdf0e10cSrcweir /*@@@ToDo 1086*cdf0e10cSrcweir Bad, bad hack, this only works if the base path 1087*cdf0e10cSrcweir really exists which is not necessary according 1088*cdf0e10cSrcweir to RFC2396 1089*cdf0e10cSrcweir The whole FileURL implementation should be merged 1090*cdf0e10cSrcweir with the rtl/uri class. 1091*cdf0e10cSrcweir */ 1092*cdf0e10cSrcweir if ( ustrBaseSysPath ) 1093*cdf0e10cSrcweir { 1094*cdf0e10cSrcweir osl_acquireMutex( g_CurrentDirectoryMutex ); 1095*cdf0e10cSrcweir 1096*cdf0e10cSrcweir GetCurrentDirectoryW( aCurrentDir.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aCurrentDir) ); 1097*cdf0e10cSrcweir SetCurrentDirectoryW( reinterpret_cast<LPCWSTR>(ustrBaseSysPath->buffer) ); 1098*cdf0e10cSrcweir } 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir dwResult = GetFullPathNameW( reinterpret_cast<LPCWSTR>(ustrRelSysPath->buffer), aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), &lpFilePart ); 1101*cdf0e10cSrcweir 1102*cdf0e10cSrcweir if ( ustrBaseSysPath ) 1103*cdf0e10cSrcweir { 1104*cdf0e10cSrcweir SetCurrentDirectoryW( ::osl::mingw_reinterpret_cast<LPCWSTR>(aCurrentDir) ); 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir osl_releaseMutex( g_CurrentDirectoryMutex ); 1107*cdf0e10cSrcweir } 1108*cdf0e10cSrcweir 1109*cdf0e10cSrcweir if ( dwResult ) 1110*cdf0e10cSrcweir { 1111*cdf0e10cSrcweir if ( dwResult >= aBuffer.getBufSizeInSymbols() ) 1112*cdf0e10cSrcweir eError = osl_File_E_INVAL; 1113*cdf0e10cSrcweir else 1114*cdf0e10cSrcweir { 1115*cdf0e10cSrcweir rtl_uString *ustrAbsSysPath = NULL; 1116*cdf0e10cSrcweir 1117*cdf0e10cSrcweir rtl_uString_newFromStr( &ustrAbsSysPath, aBuffer ); 1118*cdf0e10cSrcweir 1119*cdf0e10cSrcweir eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL ); 1120*cdf0e10cSrcweir 1121*cdf0e10cSrcweir if ( ustrAbsSysPath ) 1122*cdf0e10cSrcweir rtl_uString_release( ustrAbsSysPath ); 1123*cdf0e10cSrcweir } 1124*cdf0e10cSrcweir } 1125*cdf0e10cSrcweir else 1126*cdf0e10cSrcweir eError = oslTranslateFileError( GetLastError() ); 1127*cdf0e10cSrcweir } 1128*cdf0e10cSrcweir 1129*cdf0e10cSrcweir if ( ustrBaseSysPath ) 1130*cdf0e10cSrcweir rtl_uString_release( ustrBaseSysPath ); 1131*cdf0e10cSrcweir 1132*cdf0e10cSrcweir if ( ustrRelSysPath ) 1133*cdf0e10cSrcweir rtl_uString_release( ustrRelSysPath ); 1134*cdf0e10cSrcweir 1135*cdf0e10cSrcweir return eError; 1136*cdf0e10cSrcweir } 1137*cdf0e10cSrcweir 1138*cdf0e10cSrcweir //##################################################### 1139*cdf0e10cSrcweir oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *strRequested, rtl_uString **strValid ) 1140*cdf0e10cSrcweir { 1141*cdf0e10cSrcweir rtl_uString_newFromString(strValid, strRequested); 1142*cdf0e10cSrcweir return osl_File_E_None; 1143*cdf0e10cSrcweir } 1144