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 <ctype.h> 25 #include "system.h" 26 27 #ifndef _LIMITS_H 28 #include <limits.h> 29 #endif 30 31 #ifndef _ERRNO_H 32 #include <errno.h> 33 #endif 34 35 #ifndef _STDLIB_H_ 36 #include <stdlib.h> 37 #endif 38 39 #ifndef _STRINGS_H 40 #include <strings.h> 41 #endif 42 43 #ifndef _UNISTD_H 44 #include <unistd.h> 45 #endif 46 #include <osl/file.h> 47 #include <osl/security.h> 48 #include <rtl/uri.h> 49 #include <osl/diagnose.h> 50 #include <rtl/ustring.hxx> 51 #include <rtl/ustrbuf.h> 52 53 #ifndef _OSL_TREAD_H_ 54 #include <osl/thread.h> 55 #endif 56 #include <osl/file.hxx> 57 #include <osl/mutex.h> 58 #include <osl/process.h> 59 #include "file_error_transl.h" 60 61 #ifndef _FILE_URL_H_ 62 #include "file_url.h" 63 #endif 64 #include "file_path_helper.hxx" 65 66 #ifndef _OSL_UUNXAPI_HXX_ 67 #include "uunxapi.hxx" 68 #endif 69 70 #include <wchar.h> 71 #include <wctype.h> 72 73 /*************************************************** 74 75 General note 76 77 This file contains the part that handles File URLs. 78 79 File URLs as scheme specific notion of URIs 80 (RFC2396) may be handled platform independend, but 81 will not in osl which is considered wrong. 82 Future version of osl should handle File URLs this 83 way. In rtl/uri there is already an URI parser etc. 84 so this code should be consolidated. 85 86 **************************************************/ 87 88 oslMutex g_CurrentDirectoryMutex; 89 90 91 /*************************************************** 92 * forward 93 **************************************************/ 94 95 void _osl_warnFile(const char*, rtl_uString*); 96 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); 97 98 extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32); 99 extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); 100 101 /*************************************************** 102 * namespace directives 103 **************************************************/ 104 105 using namespace osl; 106 107 /****************************************************************************** 108 * 109 * Exported Module Functions 110 * 111 *****************************************************************************/ 112 113 /* a slightly modified version of Pchar in rtl/source/uri.c */ 114 const sal_Bool uriCharClass[128] = 115 { 116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */ 117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */ 119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */ 120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */ 121 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */ 122 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */ 123 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */ 124 }; 125 126 127 /* check for top wrong usage strings */ 128 /* 129 static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len ) 130 { 131 rtl_uString *pTmp = NULL; 132 sal_Bool bRet; 133 134 rtl_uString_newFromStr_WithLength( &pTmp, path, len ); 135 136 rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length ); 137 138 bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) || 139 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) || 140 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) || 141 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) || 142 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) ); 143 144 rtl_uString_release( pTmp ); 145 return bRet; 146 } 147 */ 148 149 150 /****************************************************************************/ 151 /* osl_getFileURLFromSystemPath */ 152 /****************************************************************************/ 153 154 BOOL WINAPI IsValidFilePathComponent( 155 LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags) 156 { 157 LPCTSTR lpComponentEnd = NULL; 158 LPCTSTR lpCurrent = lpComponent; 159 BOOL fValid = TRUE; /* Assume success */ 160 TCHAR cLast = 0; 161 162 /* Path component length must not exceed MAX_PATH */ 163 164 while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < _MAX_PATH ) 165 { 166 switch ( *lpCurrent ) 167 { 168 /* Both backslash and slash determine the end of a path component */ 169 case '\0': 170 case '/': 171 case '\\': 172 switch ( cLast ) 173 { 174 /* Component must not end with '.' or blank and can't be empty */ 175 176 case '.': 177 if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE ) 178 { 179 if ( 1 == lpCurrent - lpComponent ) 180 { 181 /* Current directory is O.K. */ 182 lpComponentEnd = lpCurrent; 183 break; 184 } 185 else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent ) 186 { 187 /* Parent directory is O.K. */ 188 lpComponentEnd = lpCurrent; 189 break; 190 } 191 } 192 case 0: 193 case ' ': 194 lpComponentEnd = lpCurrent - 1; 195 fValid = FALSE; 196 break; 197 default: 198 lpComponentEnd = lpCurrent; 199 break; 200 } 201 break; 202 /* '?' and '*' are valid wildcards but not valid file name characters */ 203 case '?': 204 case '*': 205 if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS ) 206 break; 207 /* The following characters are reserved */ 208 case '<': 209 case '>': 210 case '\"': 211 case '|': 212 case ':': 213 lpComponentEnd = lpCurrent; 214 fValid = FALSE; 215 break; 216 default: 217 /* Characters below ASCII 32 are not allowed */ 218 if ( *lpCurrent < ' ' ) 219 { 220 lpComponentEnd = lpCurrent; 221 fValid = FALSE; 222 } 223 break; 224 } 225 cLast = *lpCurrent++; 226 } 227 228 /* If we don't reached the end of the component the length of the component was to long 229 ( See condition of while loop ) */ 230 if ( !lpComponentEnd ) 231 { 232 fValid = FALSE; 233 lpComponentEnd = lpCurrent; 234 } 235 236 /* Test wether the component specifies a device name what is not allowed */ 237 238 // MT: PERFORMANCE: 239 // This is very expensive. A lot of calls to _tcsicmp. 240 // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp! 241 // Possible optimizations 242 // - Array should be const static 243 // - Sorted array, use binary search 244 // - More intelligent check for com1-9, lpt1-9 245 // Maybe make szComponent upper case, don't search case intensitive 246 // 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. 247 /* 248 if ( fValid ) 249 { 250 LPCTSTR alpDeviceNames[] = 251 { 252 TEXT("CON"), 253 TEXT("PRN"), 254 TEXT("AUX"), 255 TEXT("CLOCK$"), 256 TEXT("NUL"), 257 TEXT("LPT1"), 258 TEXT("LPT2"), 259 TEXT("LPT3"), 260 TEXT("LPT4"), 261 TEXT("LPT5"), 262 TEXT("LPT6"), 263 TEXT("LPT7"), 264 TEXT("LPT8"), 265 TEXT("LPT9"), 266 TEXT("COM1"), 267 TEXT("COM2"), 268 TEXT("COM3"), 269 TEXT("COM4"), 270 TEXT("COM5"), 271 TEXT("COM6"), 272 TEXT("COM7"), 273 TEXT("COM8"), 274 TEXT("COM9") 275 }; 276 277 TCHAR szComponent[MAX_PATH]; 278 int nComponentLength; 279 LPCTSTR lpDot; 280 int i; 281 282 // A device name with an extension is also invalid 283 lpDot = _tcschr( lpComponent, '.' ); 284 285 if ( !lpDot || lpDot > lpComponentEnd ) 286 nComponentLength = lpComponentEnd - lpComponent; 287 else 288 nComponentLength = lpDot - lpComponent; 289 290 _tcsncpy( szComponent, lpComponent, nComponentLength ); 291 szComponent[nComponentLength] = 0; 292 293 for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ ) 294 { 295 if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) ) 296 { 297 lpComponentEnd = lpComponent; 298 fValid = FALSE; 299 break; 300 } 301 } 302 } 303 */ 304 305 if ( fValid ) 306 { 307 // Empty components are not allowed 308 if ( lpComponentEnd - lpComponent < 1 ) 309 fValid = FALSE; 310 311 // If we reached the end of the string NULL is returned 312 else if ( !*lpComponentEnd ) 313 lpComponentEnd = NULL; 314 315 } 316 317 if ( lppComponentEnd ) 318 *lppComponentEnd = lpComponentEnd; 319 320 return fValid; 321 } 322 323 //##################################################### 324 DWORD WINAPI IsValidFilePath(LPCTSTR lpszPath, LPCTSTR *lppError, DWORD dwFlags) 325 { 326 LPCTSTR lpComponent; 327 BOOL fValid = TRUE; 328 DWORD dwPathType = PATHTYPE_ERROR; 329 330 if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) 331 dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE; 332 333 if ( !lpszPath ) 334 { 335 fValid = FALSE; 336 lpComponent = lpszPath; 337 } 338 339 /* Test for UNC path notation */ 340 if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) ) 341 { 342 /* Place the pointer behind the leading to backslashes */ 343 344 lpComponent = lpszPath + 2; 345 346 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE ); 347 348 /* So far we have a valid servername. Now let's see if we also have a network resource */ 349 350 dwPathType = PATHTYPE_ABSOLUTE_UNC; 351 352 if ( fValid ) 353 { 354 if ( lpComponent && !*++lpComponent ) 355 lpComponent = NULL; 356 357 if ( !lpComponent ) 358 { 359 #if 0 360 /* We only have a Server specification what is invalid */ 361 362 lpComponent = lpszPath; 363 fValid = FALSE; 364 #else 365 dwPathType |= PATHTYPE_IS_SERVER; 366 #endif 367 } 368 else 369 { 370 /* Now test the network resource */ 371 372 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 ); 373 374 /* If we now reached the end of the path, everything is O.K. */ 375 376 377 if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) ) 378 { 379 lpComponent = NULL; 380 dwPathType |= PATHTYPE_IS_VOLUME; 381 } 382 } 383 } 384 } 385 386 /* Local path verification. Must start with <drive>: */ 387 else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] ) 388 { 389 /* Place pointer behind correct drive specification */ 390 391 lpComponent = lpszPath + 2; 392 393 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) 394 lpComponent++; 395 else if ( *lpComponent ) 396 fValid = FALSE; 397 398 dwPathType = PATHTYPE_ABSOLUTE_LOCAL; 399 400 /* Now we are behind the backslash or it was a simple drive without backslash */ 401 402 if ( fValid && !*lpComponent ) 403 { 404 lpComponent = NULL; 405 dwPathType |= PATHTYPE_IS_VOLUME; 406 } 407 } 408 409 /* Can be a relative path */ 410 else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE ) 411 { 412 lpComponent = lpszPath; 413 414 /* Relative path can start with a backslash */ 415 416 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) ) 417 { 418 lpComponent++; 419 if ( !*lpComponent ) 420 lpComponent = NULL; 421 } 422 423 dwPathType = PATHTYPE_RELATIVE; 424 } 425 426 /* Anything else is an error */ 427 else 428 { 429 fValid = FALSE; 430 lpComponent = lpszPath; 431 } 432 433 /* Now validate each component of the path */ 434 while ( fValid && lpComponent ) 435 { 436 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags ); 437 438 if ( fValid && lpComponent ) 439 { 440 lpComponent++; 441 442 /* If the string behind the backslash is empty, we've done */ 443 444 if ( !*lpComponent ) 445 lpComponent = NULL; 446 } 447 } 448 449 if ( fValid && _tcslen( lpszPath ) >= _MAX_PATH ) 450 { 451 fValid = FALSE; 452 lpComponent = lpszPath + _MAX_PATH; 453 } 454 455 if ( lppError ) 456 *lppError = lpComponent; 457 458 return fValid ? dwPathType : PATHTYPE_ERROR; 459 } 460 461 sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL ) 462 { 463 sal_Char *pBuffer; 464 const sal_Char *pSrcEnd; 465 const sal_Char *pSrc; 466 sal_Char *pDest; 467 sal_Int32 nSrcLen; 468 sal_Bool bValidEncoded = sal_True; /* Assume success */ 469 470 /* The resulting decoded string length is shorter or equal to the source length */ 471 472 nSrcLen = rtl_string_getLength(strUTF8); 473 pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1)); 474 475 pDest = pBuffer; 476 pSrc = rtl_string_getStr(strUTF8); 477 pSrcEnd = pSrc + nSrcLen; 478 479 /* Now decode the URL what should result in an UTF8 string */ 480 while ( bValidEncoded && pSrc < pSrcEnd ) 481 { 482 switch ( *pSrc ) 483 { 484 case '%': 485 { 486 sal_Char aToken[3]; 487 sal_Char aChar; 488 489 pSrc++; 490 aToken[0] = *pSrc++; 491 aToken[1] = *pSrc++; 492 aToken[2] = 0; 493 494 aChar = (sal_Char)strtoul( aToken, NULL, 16 ); 495 496 /* The chars are path delimiters and must not be encoded */ 497 498 if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar ) 499 bValidEncoded = sal_False; 500 else 501 *pDest++ = aChar; 502 } 503 break; 504 default: 505 *pDest++ = *pSrc++; 506 break; 507 } 508 } 509 510 *pDest++ = 0; 511 512 if ( bValidEncoded ) { 513 rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 514 OSL_ASSERT(*pstrDecodedURL != 0); 515 } 516 517 rtl_freeMemory( pBuffer ); 518 519 return bValidEncoded; 520 } 521 522 //############################################# 523 void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL ) 524 { 525 /* Encode non ascii characters within the URL */ 526 527 rtl_String *strUTF8 = NULL; 528 sal_Char *pszEncodedURL; 529 const sal_Char *pURLScan; 530 sal_Char *pURLDest; 531 sal_Int32 nURLScanLen; 532 sal_Int32 nURLScanCount; 533 534 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 535 536 pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) ); 537 538 pURLDest = pszEncodedURL; 539 pURLScan = rtl_string_getStr( strUTF8 ); 540 nURLScanLen = rtl_string_getLength( strUTF8 ); 541 nURLScanCount = 0; 542 543 while ( nURLScanCount < nURLScanLen ) 544 { 545 sal_Char cCurrent = *pURLScan; 546 547 switch ( cCurrent ) 548 { 549 default: 550 if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) ) 551 { 552 sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent ); 553 pURLDest += 3; 554 break; 555 } 556 case '!': 557 case '\'': 558 case '(': 559 case ')': 560 case '*': 561 case '-': 562 case '.': 563 case '_': 564 case '~': 565 case '$': 566 case '&': 567 case '+': 568 case ',': 569 case '=': 570 case '@': 571 case ':': 572 case '/': 573 case '\\': 574 case '|': 575 *pURLDest++ = cCurrent; 576 break; 577 case 0: 578 break; 579 } 580 581 pURLScan++; 582 nURLScanCount++; 583 } 584 585 586 *pURLDest = 0; 587 588 rtl_string_release( strUTF8 ); 589 rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL ); 590 rtl_freeMemory( pszEncodedURL ); 591 } 592 593 //############################################# 594 oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL ) 595 { 596 oslFileError nError = osl_File_E_INVAL; /* Assume failure */ 597 rtl_uString *strTempURL = NULL; 598 DWORD dwPathType = PATHTYPE_ERROR; 599 600 if (strPath) 601 dwPathType = IsValidFilePath(strPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE); 602 603 if (dwPathType) 604 { 605 rtl_uString *strTempPath = NULL; 606 607 /* Replace backslashes */ 608 609 rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' ); 610 611 switch ( dwPathType & PATHTYPE_MASK_TYPE ) 612 { 613 case PATHTYPE_RELATIVE: 614 rtl_uString_assign( &strTempURL, strTempPath ); 615 nError = osl_File_E_None; 616 break; 617 case PATHTYPE_ABSOLUTE_UNC: 618 rtl_uString_newFromAscii( &strTempURL, "file:" ); 619 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); 620 nError = osl_File_E_None; 621 break; 622 case PATHTYPE_ABSOLUTE_LOCAL: 623 rtl_uString_newFromAscii( &strTempURL, "file:///" ); 624 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath ); 625 nError = osl_File_E_None; 626 break; 627 default: 628 break; 629 } 630 631 /* Release temp path */ 632 633 rtl_uString_release( strTempPath ); 634 } 635 636 if ( osl_File_E_None == nError ) 637 { 638 rtl_String *strEncodedURL = NULL; 639 640 /* Encode the URL */ 641 642 _osl_encodeURL( strTempURL, &strEncodedURL ); 643 644 /* Provide URL via unicode string */ 645 646 rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS ); 647 OSL_ASSERT(*pstrURL != 0); 648 rtl_string_release( strEncodedURL ); 649 } 650 651 /* Release temp URL */ 652 653 if ( strTempURL ) 654 rtl_uString_release( strTempURL ); 655 656 /* 657 OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath ); 658 */ 659 660 return nError; 661 } 662 663 oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL ) 664 { 665 return _osl_getFileURLFromSystemPath( ustrSystemPath, pustrFileURL ); 666 #if 0 667 static const sal_Unicode pDoubleSlash[2] = { '/', '/' }; 668 669 rtl_uString *pTmp = NULL; 670 sal_Int32 nIndex; 671 672 if( 0 == ustrSystemPath->length ) 673 return osl_File_E_INVAL; 674 675 /* YD convert '\' to '/' */ 676 rtl_ustr_replaceChar( ustrSystemPath->buffer, '\\', '/' ); 677 678 /* temporary hack: if already file url, return ustrSystemPath */ 679 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) ) 680 { 681 /* 682 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) ) 683 { 684 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" ); 685 rtl_uString_assign( pustrFileURL, ustrSystemPath ); 686 } 687 else 688 { 689 rtl_uString *pTmp2 = NULL; 690 691 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" ); 692 rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 ); 693 rtl_uString_newFromAscii( &pTmp2, "file://" ); 694 rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 ); 695 rtl_uString_release( pTmp2 ); 696 } 697 return osl_File_E_None; 698 */ 699 return osl_File_E_INVAL; 700 } 701 702 703 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ 704 if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] ) 705 { 706 /* check if another user is specified */ 707 if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) ) 708 { 709 /* osl_getHomeDir returns file URL */ 710 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp ); 711 712 /* remove "file://" prefix */ 713 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 ); 714 715 /* replace '~' in original string */ 716 rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp ); 717 } 718 719 else 720 { 721 /* FIXME: replace ~user with users home directory */ 722 return osl_File_E_INVAL; 723 } 724 } 725 726 /* check if initial string contains double instances of '/' */ 727 nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 ); 728 if( -1 != nIndex ) 729 { 730 sal_Int32 nSrcIndex; 731 sal_Int32 nDeleted = 0; 732 733 /* if pTmp is not already allocated, copy ustrSystemPath for modification */ 734 if( NULL == pTmp ) 735 rtl_uString_newFromString( &pTmp, ustrSystemPath ); 736 737 /* adapt index to pTmp */ 738 nIndex += pTmp->length - ustrSystemPath->length; 739 740 /* remove all occurances of '//' */ 741 for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ ) 742 { 743 if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) ) 744 nDeleted++; 745 else 746 pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex]; 747 } 748 749 /* adjust length member */ 750 pTmp->length -= nDeleted; 751 } 752 753 if( NULL == pTmp ) 754 rtl_uString_assign( &pTmp, ustrSystemPath ); 755 756 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */ 757 /* 758 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) ); 759 */ 760 761 /* file URLs must be URI encoded */ 762 rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL ); 763 764 rtl_uString_release( pTmp ); 765 766 /* absolute urls should start with 'file://' */ 767 if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] ) 768 { 769 rtl_uString *pProtocol = NULL; 770 771 rtl_uString_newFromAscii( &pProtocol, "file://" ); 772 rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL ); 773 rtl_uString_release( pProtocol ); 774 } 775 776 return osl_File_E_None; 777 #endif 778 } 779 780 //############################################# 781 oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative ) 782 { 783 rtl_String *strUTF8 = NULL; 784 rtl_uString *strDecodedURL = NULL; 785 rtl_uString *strTempPath = NULL; 786 const sal_Unicode *pDecodedURL; 787 sal_uInt32 nDecodedLen; 788 sal_Bool bValidEncoded; 789 oslFileError nError = osl_File_E_INVAL; /* Assume failure */ 790 791 /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from 792 having a mixed encoded URL later */ 793 794 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS ); 795 796 /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */ 797 798 OSL_ENSURE_FILE( 799 strUTF8->length == strURL->length || 800 0 != rtl_ustr_ascii_shortenedCompare_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 ) 801 ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL ); 802 803 bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL ); 804 805 /* Release the encoded UTF8 string */ 806 807 rtl_string_release( strUTF8 ); 808 809 810 if ( bValidEncoded ) 811 { 812 /* Replace backslashes and pipes */ 813 814 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' ); 815 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' ); 816 817 pDecodedURL = rtl_uString_getStr( strDecodedURL ); 818 nDecodedLen = rtl_uString_getLength( strDecodedURL ); 819 820 /* Must start with "file://" */ 821 822 if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) ) 823 { 824 sal_uInt32 nSkip; 825 826 if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) ) 827 nSkip = 8; 828 else if ( 829 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) || 830 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 ) 831 ) 832 nSkip = 17; 833 else 834 nSkip = 5; 835 836 /* Indicates local root */ 837 if ( nDecodedLen == nSkip ) 838 rtl_uString_newFromStr_WithLength( &strTempPath, (const sal_Unicode*)WSTR_SYSTEM_ROOT_PATH, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 ); 839 else 840 rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip ); 841 842 if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_ELLIPSE ) ) 843 nError = osl_File_E_None; 844 } 845 else if ( bAllowRelative ) /* This maybe a relative file URL */ 846 { 847 rtl_uString_assign( &strTempPath, strDecodedURL ); 848 849 if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE ) ) 850 nError = osl_File_E_None; 851 } 852 /* 853 else 854 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL ); 855 */ 856 857 } 858 859 if ( strDecodedURL ) 860 rtl_uString_release( strDecodedURL ); 861 862 if ( osl_File_E_None == nError ) 863 rtl_uString_assign( pustrPath, strTempPath ); 864 865 if ( strTempPath ) 866 rtl_uString_release( strTempPath ); 867 868 /* 869 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL ); 870 */ 871 872 return nError; 873 } 874 875 /****************************************************************************/ 876 /* osl_getSystemPathFromFileURL */ 877 /****************************************************************************/ 878 879 oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath ) 880 { 881 return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, sal_True ); 882 #if 0 883 sal_Int32 nIndex = 0; 884 rtl_uString * pTmp = NULL; 885 886 sal_Unicode encodedSlash[3] = { '%', '2', 'F' }; 887 888 /* temporary hack: if already system path, return ustrFileURL */ 889 /* 890 if( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) 891 { 892 OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" ); 893 rtl_uString_assign( pustrSystemPath, ustrFileURL ); 894 return osl_File_E_None; 895 } 896 */ 897 898 /* a valid file url may not start with '/' */ 899 if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) ) 900 { 901 return osl_File_E_INVAL; 902 } 903 904 /* search for encoded slashes (%2F) and decode every single token if we find one */ 905 if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) ) 906 { 907 rtl_uString * ustrPathToken = NULL; 908 sal_Int32 nOffset = 7; 909 910 do 911 { 912 nOffset += nIndex; 913 914 /* break url down in '/' devided tokens tokens */ 915 nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' ); 916 917 /* copy token to new string */ 918 rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset, 919 -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ ); 920 921 /* decode token */ 922 rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); 923 924 /* the result should not contain any '/' */ 925 if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) ) 926 { 927 rtl_uString_release( pTmp ); 928 rtl_uString_release( ustrPathToken ); 929 930 return osl_File_E_INVAL; 931 } 932 933 } while( -1 != nIndex ); 934 935 /* release temporary string and restore index variable */ 936 rtl_uString_release( ustrPathToken ); 937 nIndex = 0; 938 } 939 940 /* protocol and server should not be encoded, so decode the whole string */ 941 rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); 942 943 /* check if file protocol specified */ 944 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ 945 if( 7 <= pTmp->length ) 946 { 947 rtl_uString * pProtocol = NULL; 948 rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 ); 949 950 /* protocol is case insensitive */ 951 rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length ); 952 953 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) ) 954 nIndex = 7; 955 956 rtl_uString_release( pProtocol ); 957 } 958 959 /* skip "localhost" or "127.0.0.1" if "file://" is specified */ 960 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ 961 if( nIndex && ( 10 <= pTmp->length - nIndex ) ) 962 { 963 rtl_uString * pServer = NULL; 964 rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 ); 965 966 /* server is case insensitive */ 967 rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length ); 968 969 if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) || 970 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) ) 971 { 972 /* don't exclude the '/' */ 973 nIndex += 9; 974 } 975 976 rtl_uString_release( pServer ); 977 } 978 979 if( nIndex ) 980 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex ); 981 982 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ 983 if( (sal_Unicode) '~' == pTmp->buffer[0] ) 984 { 985 /* check if another user is specified */ 986 if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) ) 987 { 988 rtl_uString *pTmp2 = NULL; 989 990 /* osl_getHomeDir returns file URL */ 991 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 ); 992 993 /* remove "file://" prefix */ 994 rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 ); 995 996 /* replace '~' in original string */ 997 rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 ); 998 rtl_uString_release( pTmp2 ); 999 } 1000 1001 else 1002 { 1003 /* FIXME: replace ~user with users home directory */ 1004 return osl_File_E_INVAL; 1005 } 1006 } 1007 1008 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */ 1009 /* 1010 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) ); 1011 */ 1012 1013 *pustrSystemPath = pTmp; 1014 return osl_File_E_None; 1015 #endif // 0 1016 } 1017 1018 1019 /**************************************************************************** 1020 * osl_getSystemPathFromFileURL_Ex - helper function 1021 * clients may specify if they want to accept relative 1022 * URLs or not 1023 ****************************************************************************/ 1024 1025 oslFileError osl_getSystemPathFromFileURL_Ex( 1026 rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative) 1027 { 1028 return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, bAllowRelative); 1029 #if 0 1030 rtl_uString* temp = 0; 1031 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp); 1032 1033 if (osl_File_E_None == osl_error) 1034 { 1035 if (bAllowRelative 1036 || (UNICHAR_SLASH == temp->buffer[0]) 1037 || (UNICHAR_COLON == temp->buffer[1] && UNICHAR_SLASH == temp->buffer[2])) 1038 { 1039 *pustrSystemPath = temp; 1040 } 1041 else 1042 { 1043 rtl_uString_release(temp); 1044 osl_error = osl_File_E_INVAL; 1045 } 1046 } 1047 1048 return osl_error; 1049 #endif 1050 } 1051 1052 namespace /* private */ 1053 { 1054 1055 #if 0 // YD 1056 1057 /****************************************************** 1058 * Helper function, return a pinter to the final '\0' 1059 * of a string 1060 ******************************************************/ 1061 1062 sal_Unicode* ustrtoend(sal_Unicode* pStr) 1063 { 1064 return (pStr + rtl_ustr_getLength(pStr)); 1065 } 1066 1067 /********************************************* 1068 1069 ********************************************/ 1070 sal_Unicode* ustrcpy(const sal_Unicode* s, sal_Unicode* d) 1071 { 1072 const sal_Unicode* sc = s; 1073 sal_Unicode* dc = d; 1074 1075 while ((*dc++ = *sc++)) 1076 /**/; 1077 1078 return d; 1079 } 1080 1081 /********************************************* 1082 1083 ********************************************/ 1084 1085 sal_Unicode* ustrncpy(const sal_Unicode* s, sal_Unicode* d, unsigned int n) 1086 { 1087 const sal_Unicode* sc = s; 1088 sal_Unicode* dc = d; 1089 unsigned int i = n; 1090 1091 while (i--) 1092 *dc++ = *sc++; 1093 1094 if (n) 1095 *dc = 0; 1096 1097 return d; 1098 } 1099 1100 /********************************************* 1101 1102 ********************************************/ 1103 1104 sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d) 1105 { 1106 sal_Unicode* p = ustrtoend(d); 1107 *p++ = chr; 1108 *p = 0; 1109 return d; 1110 } 1111 1112 /********************************************* 1113 1114 ********************************************/ 1115 1116 sal_Unicode* ustrcat(const sal_Unicode* s, sal_Unicode* d) 1117 { 1118 sal_Unicode* dc = ustrtoend(d); 1119 ustrcpy(s, dc); 1120 return d; 1121 } 1122 1123 /****************************************************** 1124 * 1125 ******************************************************/ 1126 1127 bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr) 1128 { 1129 sal_Unicode* p = ustrtoend(pStr); 1130 if (p > pStr) 1131 p--; 1132 return (*p == Chr); 1133 } 1134 1135 /****************************************************** 1136 * Ensure that the given string has the specified last 1137 * character if necessary append it 1138 ******************************************************/ 1139 1140 sal_Unicode* _strensurelast(sal_Unicode* pStr, sal_Unicode Chr) 1141 { 1142 if (!_islastchr(pStr, Chr)) 1143 ustrchrcat(Chr, pStr); 1144 return pStr; 1145 } 1146 1147 /****************************************************** 1148 * Remove the last part of a path, a path that has 1149 * only a '/' or no '/' at all will be returned 1150 * unmodified 1151 ******************************************************/ 1152 1153 sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath) 1154 { 1155 /* we always may skip -2 because we 1156 may at least stand on a '/' but 1157 either there is no other character 1158 before this '/' or it's another 1159 character than the '/' 1160 */ 1161 sal_Unicode* p = ustrtoend(aPath) - 2; 1162 1163 // move back to the next path separator 1164 // or to the start of the string 1165 while ((p > aPath) && (*p != UNICHAR_SLASH)) 1166 p--; 1167 1168 if (p >= aPath) 1169 { 1170 if (UNICHAR_SLASH == *p) 1171 { 1172 p++; 1173 *p = '\0'; 1174 } 1175 else 1176 { 1177 *p = '\0'; 1178 } 1179 } 1180 1181 return aPath; 1182 } 1183 1184 /****************************************************** 1185 * 1186 ******************************************************/ 1187 1188 oslFileError _osl_resolvepath( 1189 /*inout*/ sal_Unicode* path, 1190 /*inout*/ sal_Unicode* current_pos, 1191 /*in */ sal_Unicode* sentinel, 1192 /*inout*/ bool* failed) 1193 { 1194 oslFileError ferr = osl_File_E_None; 1195 1196 if (!*failed) 1197 { 1198 char unresolved_path[PATH_MAX]; 1199 if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path))) 1200 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1201 1202 char resolved_path[PATH_MAX]; 1203 if (realpath(unresolved_path, resolved_path)) 1204 { 1205 if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX)) 1206 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1207 1208 current_pos = ustrtoend(path) - 1; 1209 } 1210 else 1211 { 1212 if (EACCES == errno || ENOTDIR == errno || ENOENT == errno) 1213 *failed = true; 1214 else 1215 ferr = oslTranslateFileError(OSL_FET_ERROR, errno); 1216 } 1217 } 1218 1219 return ferr; 1220 } 1221 1222 /****************************************************** 1223 * Works even with non existing paths. The resulting 1224 * path must not exceed PATH_MAX else 1225 * osl_File_E_NAMETOOLONG is the result 1226 ******************************************************/ 1227 1228 oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path) 1229 { 1230 // the given unresolved path must not exceed PATH_MAX 1231 if (unresolved_path.getLength() >= (PATH_MAX - 2)) 1232 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1233 1234 sal_Unicode path_resolved_so_far[PATH_MAX]; 1235 const sal_Unicode* punresolved = unresolved_path.getStr(); 1236 sal_Unicode* presolvedsf = path_resolved_so_far; 1237 1238 // reserve space for leading '/' and trailing '\0' 1239 // do not exceed this limit 1240 sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2; 1241 1242 // if realpath fails with error ENOTDIR, EACCES or ENOENT 1243 // we will not call it again, because _osl_realpath should also 1244 // work with non existing directories etc. 1245 bool realpath_failed = false; 1246 oslFileError ferr; 1247 1248 path_resolved_so_far[0] = '\0'; 1249 1250 while (*punresolved != '\0') 1251 { 1252 // ignore '/.' , skip one part back when '/..' 1253 1254 if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf)) 1255 { 1256 if ('\0' == *(punresolved + 1)) 1257 { 1258 punresolved++; 1259 continue; 1260 } 1261 else if (UNICHAR_SLASH == *(punresolved + 1)) 1262 { 1263 punresolved += 2; 1264 continue; 1265 } 1266 else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2)))) 1267 { 1268 _rmlastpathtoken(path_resolved_so_far); 1269 1270 presolvedsf = ustrtoend(path_resolved_so_far) - 1; 1271 1272 if (UNICHAR_SLASH == *(punresolved + 2)) 1273 punresolved += 3; 1274 else 1275 punresolved += 2; 1276 1277 continue; 1278 } 1279 else // a file or directory name may start with '.' 1280 { 1281 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) 1282 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1283 1284 ustrchrcat(*punresolved++, path_resolved_so_far); 1285 1286 if ('\0' == *punresolved && !realpath_failed) 1287 { 1288 ferr = _osl_resolvepath( 1289 path_resolved_so_far, 1290 presolvedsf, 1291 sentinel, 1292 &realpath_failed); 1293 1294 if (osl_File_E_None != ferr) 1295 return ferr; 1296 } 1297 } 1298 } 1299 else if (UNICHAR_SLASH == *punresolved) 1300 { 1301 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) 1302 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1303 1304 ustrchrcat(*punresolved++, path_resolved_so_far); 1305 1306 if (!realpath_failed) 1307 { 1308 ferr = _osl_resolvepath( 1309 path_resolved_so_far, 1310 presolvedsf, 1311 sentinel, 1312 &realpath_failed); 1313 1314 if (osl_File_E_None != ferr) 1315 return ferr; 1316 1317 if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH)) 1318 { 1319 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) 1320 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1321 1322 ustrchrcat(UNICHAR_SLASH, path_resolved_so_far); 1323 } 1324 } 1325 } 1326 else // any other character 1327 { 1328 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel) 1329 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG); 1330 1331 ustrchrcat(*punresolved++, path_resolved_so_far); 1332 1333 if ('\0' == *punresolved && !realpath_failed) 1334 { 1335 ferr = _osl_resolvepath( 1336 path_resolved_so_far, 1337 presolvedsf, 1338 sentinel, 1339 &realpath_failed); 1340 1341 if (osl_File_E_None != ferr) 1342 return ferr; 1343 } 1344 } 1345 } 1346 1347 sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far); 1348 1349 OSL_ASSERT(len < PATH_MAX); 1350 1351 resolved_path = rtl::OUString(path_resolved_so_far, len); 1352 1353 return osl_File_E_None; 1354 } 1355 1356 #endif // 0 // YD 1357 1358 } // end namespace private 1359 1360 #if OSL_DEBUG_LEVEL > 0 1361 1362 //##################################################### 1363 void _osl_warnFile( const char *message, rtl_uString *ustrFile ) 1364 { 1365 char szBuffer[2048]; 1366 1367 if (ustrFile) 1368 { 1369 rtl_String *strFile = NULL; 1370 1371 rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); 1372 snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer ); 1373 rtl_string_release( strFile ); 1374 1375 message = szBuffer; 1376 } 1377 OSL_ENSURE( 0, message ); 1378 } 1379 1380 #endif // OSL_DEBUG_LEVEL > 0 1381 1382 /****************************************************** 1383 * osl_getAbsoluteFileURL 1384 ******************************************************/ 1385 1386 //oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL) 1387 oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL ) 1388 { 1389 oslFileError eError; 1390 rtl_uString *ustrRelSysPath = NULL; 1391 rtl_uString *ustrBaseSysPath = NULL; 1392 1393 if ( ustrBaseURL && ustrBaseURL->length ) 1394 { 1395 eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False ); 1396 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" ); 1397 1398 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True ); 1399 } 1400 else 1401 { 1402 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False ); 1403 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" ); 1404 } 1405 1406 if ( !eError ) 1407 { 1408 CHAR szBuffer[_MAX_PATH]; 1409 CHAR szRelSysPath[_MAX_PATH]; 1410 CHAR szCurrentDir[_MAX_PATH]; 1411 int result; 1412 char* cwd; 1413 int rc; 1414 1415 /*@@@ToDo 1416 Bad, bad hack, this only works if the base path 1417 really exists which is not necessary according 1418 to RFC2396 1419 The whole FileURL implementation should be merged 1420 with the rtl/uri class. 1421 */ 1422 if ( ustrBaseSysPath ) 1423 { 1424 CHAR szBaseSysPath[_MAX_PATH]; 1425 1426 if (!g_CurrentDirectoryMutex) 1427 g_CurrentDirectoryMutex = osl_createMutex(); 1428 1429 osl_acquireMutex( g_CurrentDirectoryMutex ); 1430 1431 cwd = getcwd( szCurrentDir, sizeof(szCurrentDir) ); 1432 UnicodeToText( szBaseSysPath, sizeof(szBaseSysPath), ustrBaseSysPath->buffer, ustrBaseSysPath->length); 1433 rc = chdir( szBaseSysPath); 1434 } 1435 1436 UnicodeToText( szRelSysPath, sizeof(szRelSysPath), ustrRelSysPath->buffer, ustrRelSysPath->length); 1437 result = !_abspath( szBuffer, szRelSysPath, sizeof(szBuffer)); 1438 1439 if ( ustrBaseSysPath ) 1440 { 1441 rc = chdir( szCurrentDir ); 1442 1443 osl_releaseMutex( g_CurrentDirectoryMutex ); 1444 } 1445 1446 if ( result ) 1447 { 1448 rtl_uString *ustrAbsSysPath = NULL; 1449 1450 oslMakeUStrFromPsz( szBuffer, &ustrAbsSysPath); 1451 1452 eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL ); 1453 1454 if ( ustrAbsSysPath ) 1455 rtl_uString_release( ustrAbsSysPath ); 1456 } 1457 else 1458 eError = osl_File_E_INVAL; 1459 } 1460 1461 if ( ustrBaseSysPath ) 1462 rtl_uString_release( ustrBaseSysPath ); 1463 1464 if ( ustrRelSysPath ) 1465 rtl_uString_release( ustrRelSysPath ); 1466 1467 return eError; 1468 #if 0 1469 FileBase::RC rc; 1470 rtl::OUString unresolved_path; 1471 1472 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path); 1473 1474 if(FileBase::E_None != rc) 1475 return oslFileError(rc); 1476 1477 if (systemPathIsRelativePath(unresolved_path)) 1478 { 1479 rtl::OUString base_path; 1480 rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False); 1481 1482 if (FileBase::E_None != rc) 1483 return oslFileError(rc); 1484 1485 rtl::OUString abs_path; 1486 systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path); 1487 1488 unresolved_path = abs_path; 1489 } 1490 1491 rtl::OUString resolved_path; 1492 rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path); 1493 1494 if (FileBase::E_None == rc) 1495 { 1496 rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL); 1497 OSL_ASSERT(FileBase::E_None == rc); 1498 } 1499 1500 return oslFileError(rc); 1501 #endif // 0 1502 } 1503 1504 1505 namespace /* private */ 1506 { 1507 1508 /********************************************* 1509 No separate error code if unicode to text 1510 conversion or getenv fails because for the 1511 caller there is no difference why a file 1512 could not be found in $PATH 1513 ********************************************/ 1514 1515 bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result) 1516 { 1517 bool bfound = false; 1518 rtl::OUString path = rtl::OUString::createFromAscii("PATH"); 1519 rtl::OUString env_path; 1520 1521 if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData)) 1522 bfound = osl::searchPath(file_path, env_path, result); 1523 1524 return bfound; 1525 } 1526 1527 /********************************************* 1528 No separate error code if unicode to text 1529 conversion or getcwd fails because for the 1530 caller there is no difference why a file 1531 could not be found in CDW 1532 ********************************************/ 1533 1534 bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result) 1535 { 1536 bool bfound = false; 1537 rtl::OUString cwd_url; 1538 1539 if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData)) 1540 { 1541 rtl::OUString cwd; 1542 FileBase::getSystemPathFromFileURL(cwd_url, cwd); 1543 bfound = osl::searchPath(file_path, cwd, result); 1544 } 1545 return bfound; 1546 } 1547 1548 /********************************************* 1549 1550 ********************************************/ 1551 1552 bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result) 1553 { 1554 return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result)); 1555 } 1556 1557 } // end namespace private 1558 1559 1560 /**************************************************************************** 1561 * osl_searchFileURL 1562 ***************************************************************************/ 1563 1564 oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL) 1565 { 1566 OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter"); 1567 1568 FileBase::RC rc; 1569 rtl::OUString file_path; 1570 1571 // try to interpret search path as file url else assume it's a system path list 1572 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path); 1573 if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc)) 1574 file_path = ustrFilePath; 1575 else if (FileBase::E_None != rc) 1576 return oslFileError(rc); 1577 1578 bool bfound = false; 1579 rtl::OUString result; 1580 1581 if (find_in_searchPath(file_path, ustrSearchPath, result) || 1582 find_in_PATH(file_path, result) || 1583 find_in_CWD(file_path, result)) 1584 { 1585 rtl::OUString resolved; 1586 1587 if (osl::realpath(result, resolved)) 1588 { 1589 #if OSL_DEBUG_LEVEL > 0 1590 oslFileError osl_error = 1591 #endif 1592 osl_getFileURLFromSystemPath(resolved.pData, pustrURL); 1593 OSL_ASSERT(osl_File_E_None == osl_error); 1594 bfound = true; 1595 } 1596 } 1597 return bfound ? osl_File_E_None : osl_File_E_NOENT; 1598 } 1599 1600 1601 /**************************************************************************** 1602 * FileURLToPath 1603 ***************************************************************************/ 1604 1605 oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL) 1606 { 1607 rtl_uString* ustrSystemPath = NULL; 1608 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath); 1609 1610 if(osl_File_E_None != osl_error) 1611 return osl_error; 1612 1613 osl_systemPathRemoveSeparator(ustrSystemPath); 1614 1615 /* convert unicode path to text */ 1616 if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length)) 1617 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno); 1618 1619 rtl_uString_release(ustrSystemPath); 1620 1621 return osl_error; 1622 } 1623