update dev300-m57
[ooovba.git] / sal / osl / os2 / file_url.cxx
blob0fa5ea03a81be6689caf2a847d596962c2c9773f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: file_url.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include <ctype.h>
32 #include "system.h"
34 #ifndef _LIMITS_H
35 #include <limits.h>
36 #endif
38 #ifndef _ERRNO_H
39 #include <errno.h>
40 #endif
42 #ifndef _STDLIB_H_
43 #include <stdlib.h>
44 #endif
46 #ifndef _STRINGS_H
47 #include <strings.h>
48 #endif
50 #ifndef _UNISTD_H
51 #include <unistd.h>
52 #endif
53 #include <osl/file.h>
54 #include <osl/security.h>
55 #include <rtl/uri.h>
56 #include <osl/diagnose.h>
57 #include <rtl/ustring.hxx>
58 #include <rtl/ustrbuf.h>
60 #ifndef _OSL_TREAD_H_
61 #include <osl/thread.h>
62 #endif
63 #include <osl/file.hxx>
64 #include <osl/mutex.h>
65 #include <osl/process.h>
66 #include "file_error_transl.h"
68 #ifndef _FILE_URL_H_
69 #include "file_url.h"
70 #endif
71 #include "file_path_helper.hxx"
73 #ifndef _OSL_UUNXAPI_HXX_
74 #include "uunxapi.hxx"
75 #endif
77 #include <wchar.h>
78 #include <wctype.h>
80 /***************************************************
82 General note
84 This file contains the part that handles File URLs.
86 File URLs as scheme specific notion of URIs
87 (RFC2396) may be handled platform independend, but
88 will not in osl which is considered wrong.
89 Future version of osl should handle File URLs this
90 way. In rtl/uri there is already an URI parser etc.
91 so this code should be consolidated.
93 **************************************************/
95 oslMutex g_CurrentDirectoryMutex;
98 /***************************************************
99 * forward
100 **************************************************/
102 void _osl_warnFile(const char*, rtl_uString*);
103 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr);
105 extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
106 extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
108 /***************************************************
109 * namespace directives
110 **************************************************/
112 using namespace osl;
114 /******************************************************************************
116 * Exported Module Functions
118 *****************************************************************************/
120 /* a slightly modified version of Pchar in rtl/source/uri.c */
121 const sal_Bool uriCharClass[128] =
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
126 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
129 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
134 /* check for top wrong usage strings */
136 static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
138 rtl_uString *pTmp = NULL;
139 sal_Bool bRet;
141 rtl_uString_newFromStr_WithLength( &pTmp, path, len );
143 rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
145 bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
146 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
147 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
148 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
149 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
151 rtl_uString_release( pTmp );
152 return bRet;
157 /****************************************************************************/
158 /* osl_getFileURLFromSystemPath */
159 /****************************************************************************/
161 BOOL WINAPI IsValidFilePathComponent(
162 LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
164 LPCTSTR lpComponentEnd = NULL;
165 LPCTSTR lpCurrent = lpComponent;
166 BOOL fValid = TRUE; /* Assume success */
167 TCHAR cLast = 0;
169 /* Path component length must not exceed MAX_PATH */
171 while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < _MAX_PATH )
173 switch ( *lpCurrent )
175 /* Both backslash and slash determine the end of a path component */
176 case '\0':
177 case '/':
178 case '\\':
179 switch ( cLast )
181 /* Component must not end with '.' or blank and can't be empty */
183 case '.':
184 if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
186 if ( 1 == lpCurrent - lpComponent )
188 /* Current directory is O.K. */
189 lpComponentEnd = lpCurrent;
190 break;
192 else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
194 /* Parent directory is O.K. */
195 lpComponentEnd = lpCurrent;
196 break;
199 case 0:
200 case ' ':
201 lpComponentEnd = lpCurrent - 1;
202 fValid = FALSE;
203 break;
204 default:
205 lpComponentEnd = lpCurrent;
206 break;
208 break;
209 /* '?' and '*' are valid wildcards but not valid file name characters */
210 case '?':
211 case '*':
212 if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
213 break;
214 /* The following characters are reserved */
215 case '<':
216 case '>':
217 case '\"':
218 case '|':
219 case ':':
220 lpComponentEnd = lpCurrent;
221 fValid = FALSE;
222 break;
223 default:
224 /* Characters below ASCII 32 are not allowed */
225 if ( *lpCurrent < ' ' )
227 lpComponentEnd = lpCurrent;
228 fValid = FALSE;
230 break;
232 cLast = *lpCurrent++;
235 /* If we don't reached the end of the component the length of the component was to long
236 ( See condition of while loop ) */
237 if ( !lpComponentEnd )
239 fValid = FALSE;
240 lpComponentEnd = lpCurrent;
243 /* Test wether the component specifies a device name what is not allowed */
245 // MT: PERFORMANCE:
246 // This is very expensive. A lot of calls to _tcsicmp.
247 // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
248 // Possible optimizations
249 // - Array should be const static
250 // - Sorted array, use binary search
251 // - More intelligent check for com1-9, lpt1-9
252 // Maybe make szComponent upper case, don't search case intensitive
253 // 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.
255 if ( fValid )
257 LPCTSTR alpDeviceNames[] =
259 TEXT("CON"),
260 TEXT("PRN"),
261 TEXT("AUX"),
262 TEXT("CLOCK$"),
263 TEXT("NUL"),
264 TEXT("LPT1"),
265 TEXT("LPT2"),
266 TEXT("LPT3"),
267 TEXT("LPT4"),
268 TEXT("LPT5"),
269 TEXT("LPT6"),
270 TEXT("LPT7"),
271 TEXT("LPT8"),
272 TEXT("LPT9"),
273 TEXT("COM1"),
274 TEXT("COM2"),
275 TEXT("COM3"),
276 TEXT("COM4"),
277 TEXT("COM5"),
278 TEXT("COM6"),
279 TEXT("COM7"),
280 TEXT("COM8"),
281 TEXT("COM9")
284 TCHAR szComponent[MAX_PATH];
285 int nComponentLength;
286 LPCTSTR lpDot;
287 int i;
289 // A device name with an extension is also invalid
290 lpDot = _tcschr( lpComponent, '.' );
292 if ( !lpDot || lpDot > lpComponentEnd )
293 nComponentLength = lpComponentEnd - lpComponent;
294 else
295 nComponentLength = lpDot - lpComponent;
297 _tcsncpy( szComponent, lpComponent, nComponentLength );
298 szComponent[nComponentLength] = 0;
300 for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
302 if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
304 lpComponentEnd = lpComponent;
305 fValid = FALSE;
306 break;
312 if ( fValid )
314 // Empty components are not allowed
315 if ( lpComponentEnd - lpComponent < 1 )
316 fValid = FALSE;
318 // If we reached the end of the string NULL is returned
319 else if ( !*lpComponentEnd )
320 lpComponentEnd = NULL;
324 if ( lppComponentEnd )
325 *lppComponentEnd = lpComponentEnd;
327 return fValid;
330 //#####################################################
331 DWORD WINAPI IsValidFilePath(LPCTSTR lpszPath, LPCTSTR *lppError, DWORD dwFlags)
333 LPCTSTR lpComponent;
334 BOOL fValid = TRUE;
335 DWORD dwPathType = PATHTYPE_ERROR;
337 if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
338 dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
340 if ( !lpszPath )
342 fValid = FALSE;
343 lpComponent = lpszPath;
346 /* Test for UNC path notation */
347 if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
349 /* Place the pointer behind the leading to backslashes */
351 lpComponent = lpszPath + 2;
353 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
355 /* So far we have a valid servername. Now let's see if we also have a network resource */
357 dwPathType = PATHTYPE_ABSOLUTE_UNC;
359 if ( fValid )
361 if ( lpComponent && !*++lpComponent )
362 lpComponent = NULL;
364 if ( !lpComponent )
366 #if 0
367 /* We only have a Server specification what is invalid */
369 lpComponent = lpszPath;
370 fValid = FALSE;
371 #else
372 dwPathType |= PATHTYPE_IS_SERVER;
373 #endif
375 else
377 /* Now test the network resource */
379 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
381 /* If we now reached the end of the path, everything is O.K. */
384 if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
386 lpComponent = NULL;
387 dwPathType |= PATHTYPE_IS_VOLUME;
393 /* Local path verification. Must start with <drive>: */
394 else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
396 /* Place pointer behind correct drive specification */
398 lpComponent = lpszPath + 2;
400 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
401 lpComponent++;
402 else if ( *lpComponent )
403 fValid = FALSE;
405 dwPathType = PATHTYPE_ABSOLUTE_LOCAL;
407 /* Now we are behind the backslash or it was a simple drive without backslash */
409 if ( fValid && !*lpComponent )
411 lpComponent = NULL;
412 dwPathType |= PATHTYPE_IS_VOLUME;
416 /* Can be a relative path */
417 else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
419 lpComponent = lpszPath;
421 /* Relative path can start with a backslash */
423 if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
425 lpComponent++;
426 if ( !*lpComponent )
427 lpComponent = NULL;
430 dwPathType = PATHTYPE_RELATIVE;
433 /* Anything else is an error */
434 else
436 fValid = FALSE;
437 lpComponent = lpszPath;
440 /* Now validate each component of the path */
441 while ( fValid && lpComponent )
443 fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
445 if ( fValid && lpComponent )
447 lpComponent++;
449 /* If the string behind the backslash is empty, we've done */
451 if ( !*lpComponent )
452 lpComponent = NULL;
456 if ( fValid && _tcslen( lpszPath ) >= _MAX_PATH )
458 fValid = FALSE;
459 lpComponent = lpszPath + _MAX_PATH;
462 if ( lppError )
463 *lppError = lpComponent;
465 return fValid ? dwPathType : PATHTYPE_ERROR;
468 sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
470 sal_Char *pBuffer;
471 const sal_Char *pSrcEnd;
472 const sal_Char *pSrc;
473 sal_Char *pDest;
474 sal_Int32 nSrcLen;
475 sal_Bool bValidEncoded = sal_True; /* Assume success */
477 /* The resulting decoded string length is shorter or equal to the source length */
479 nSrcLen = rtl_string_getLength(strUTF8);
480 pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
482 pDest = pBuffer;
483 pSrc = rtl_string_getStr(strUTF8);
484 pSrcEnd = pSrc + nSrcLen;
486 /* Now decode the URL what should result in an UTF8 string */
487 while ( bValidEncoded && pSrc < pSrcEnd )
489 switch ( *pSrc )
491 case '%':
493 sal_Char aToken[3];
494 sal_Char aChar;
496 pSrc++;
497 aToken[0] = *pSrc++;
498 aToken[1] = *pSrc++;
499 aToken[2] = 0;
501 aChar = (sal_Char)strtoul( aToken, NULL, 16 );
503 /* The chars are path delimiters and must not be encoded */
505 if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
506 bValidEncoded = sal_False;
507 else
508 *pDest++ = aChar;
510 break;
511 default:
512 *pDest++ = *pSrc++;
513 break;
517 *pDest++ = 0;
519 if ( bValidEncoded ) {
520 rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
521 OSL_ASSERT(*pstrDecodedURL != 0);
524 rtl_freeMemory( pBuffer );
526 return bValidEncoded;
529 //#############################################
530 void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
532 /* Encode non ascii characters within the URL */
534 rtl_String *strUTF8 = NULL;
535 sal_Char *pszEncodedURL;
536 const sal_Char *pURLScan;
537 sal_Char *pURLDest;
538 sal_Int32 nURLScanLen;
539 sal_Int32 nURLScanCount;
541 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
543 pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
545 pURLDest = pszEncodedURL;
546 pURLScan = rtl_string_getStr( strUTF8 );
547 nURLScanLen = rtl_string_getLength( strUTF8 );
548 nURLScanCount = 0;
550 while ( nURLScanCount < nURLScanLen )
552 sal_Char cCurrent = *pURLScan;
554 switch ( cCurrent )
556 default:
557 if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
559 sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
560 pURLDest += 3;
561 break;
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 case ',':
576 case '=':
577 case '@':
578 case ':':
579 case '/':
580 case '\\':
581 case '|':
582 *pURLDest++ = cCurrent;
583 break;
584 case 0:
585 break;
588 pURLScan++;
589 nURLScanCount++;
593 *pURLDest = 0;
595 rtl_string_release( strUTF8 );
596 rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
597 rtl_freeMemory( pszEncodedURL );
600 //#############################################
601 oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
603 oslFileError nError = osl_File_E_INVAL; /* Assume failure */
604 rtl_uString *strTempURL = NULL;
605 DWORD dwPathType = PATHTYPE_ERROR;
607 if (strPath)
608 dwPathType = IsValidFilePath(strPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE);
610 if (dwPathType)
612 rtl_uString *strTempPath = NULL;
614 /* Replace backslashes */
616 rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
618 switch ( dwPathType & PATHTYPE_MASK_TYPE )
620 case PATHTYPE_RELATIVE:
621 rtl_uString_assign( &strTempURL, strTempPath );
622 nError = osl_File_E_None;
623 break;
624 case PATHTYPE_ABSOLUTE_UNC:
625 rtl_uString_newFromAscii( &strTempURL, "file:" );
626 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
627 nError = osl_File_E_None;
628 break;
629 case PATHTYPE_ABSOLUTE_LOCAL:
630 rtl_uString_newFromAscii( &strTempURL, "file:///" );
631 rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
632 nError = osl_File_E_None;
633 break;
634 default:
635 break;
638 /* Release temp path */
640 rtl_uString_release( strTempPath );
643 if ( osl_File_E_None == nError )
645 rtl_String *strEncodedURL = NULL;
647 /* Encode the URL */
649 _osl_encodeURL( strTempURL, &strEncodedURL );
651 /* Provide URL via unicode string */
653 rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
654 OSL_ASSERT(*pstrURL != 0);
655 rtl_string_release( strEncodedURL );
658 /* Release temp URL */
660 if ( strTempURL )
661 rtl_uString_release( strTempURL );
664 OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
667 return nError;
670 oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
672 return _osl_getFileURLFromSystemPath( ustrSystemPath, pustrFileURL );
673 #if 0
674 static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
676 rtl_uString *pTmp = NULL;
677 sal_Int32 nIndex;
679 if( 0 == ustrSystemPath->length )
680 return osl_File_E_INVAL;
682 /* YD convert '\' to '/' */
683 rtl_ustr_replaceChar( ustrSystemPath->buffer, '\\', '/' );
685 /* temporary hack: if already file url, return ustrSystemPath */
686 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) )
689 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
691 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
692 rtl_uString_assign( pustrFileURL, ustrSystemPath );
694 else
696 rtl_uString *pTmp2 = NULL;
698 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
699 rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
700 rtl_uString_newFromAscii( &pTmp2, "file://" );
701 rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
702 rtl_uString_release( pTmp2 );
704 return osl_File_E_None;
706 return osl_File_E_INVAL;
710 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
711 if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] )
713 /* check if another user is specified */
714 if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) )
716 /* osl_getHomeDir returns file URL */
717 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp );
719 /* remove "file://" prefix */
720 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
722 /* replace '~' in original string */
723 rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
726 else
728 /* FIXME: replace ~user with users home directory */
729 return osl_File_E_INVAL;
733 /* check if initial string contains double instances of '/' */
734 nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
735 if( -1 != nIndex )
737 sal_Int32 nSrcIndex;
738 sal_Int32 nDeleted = 0;
740 /* if pTmp is not already allocated, copy ustrSystemPath for modification */
741 if( NULL == pTmp )
742 rtl_uString_newFromString( &pTmp, ustrSystemPath );
744 /* adapt index to pTmp */
745 nIndex += pTmp->length - ustrSystemPath->length;
747 /* remove all occurances of '//' */
748 for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
750 if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) )
751 nDeleted++;
752 else
753 pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
756 /* adjust length member */
757 pTmp->length -= nDeleted;
760 if( NULL == pTmp )
761 rtl_uString_assign( &pTmp, ustrSystemPath );
763 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
765 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
768 /* file URLs must be URI encoded */
769 rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
771 rtl_uString_release( pTmp );
773 /* absolute urls should start with 'file://' */
774 if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] )
776 rtl_uString *pProtocol = NULL;
778 rtl_uString_newFromAscii( &pProtocol, "file://" );
779 rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
780 rtl_uString_release( pProtocol );
783 return osl_File_E_None;
784 #endif
787 //#############################################
788 oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
790 rtl_String *strUTF8 = NULL;
791 rtl_uString *strDecodedURL = NULL;
792 rtl_uString *strTempPath = NULL;
793 const sal_Unicode *pDecodedURL;
794 sal_uInt32 nDecodedLen;
795 sal_Bool bValidEncoded;
796 oslFileError nError = osl_File_E_INVAL; /* Assume failure */
798 /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
799 having a mixed encoded URL later */
801 rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
803 /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
805 OSL_ENSURE_FILE(
806 strUTF8->length == strURL->length ||
807 0 != rtl_ustr_ascii_shortenedCompare_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
808 ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
810 bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
812 /* Release the encoded UTF8 string */
814 rtl_string_release( strUTF8 );
817 if ( bValidEncoded )
819 /* Replace backslashes and pipes */
821 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
822 rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
824 pDecodedURL = rtl_uString_getStr( strDecodedURL );
825 nDecodedLen = rtl_uString_getLength( strDecodedURL );
827 /* Must start with "file://" */
829 if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
831 sal_uInt32 nSkip;
833 if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
834 nSkip = 8;
835 else if (
836 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
837 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
839 nSkip = 17;
840 else
841 nSkip = 5;
843 /* Indicates local root */
844 if ( nDecodedLen == nSkip )
845 rtl_uString_newFromStr_WithLength( &strTempPath, (const sal_Unicode*)WSTR_SYSTEM_ROOT_PATH, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
846 else
847 rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
849 if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_ELLIPSE ) )
850 nError = osl_File_E_None;
852 else if ( bAllowRelative ) /* This maybe a relative file URL */
854 rtl_uString_assign( &strTempPath, strDecodedURL );
856 if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE ) )
857 nError = osl_File_E_None;
860 else
861 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
866 if ( strDecodedURL )
867 rtl_uString_release( strDecodedURL );
869 if ( osl_File_E_None == nError )
870 rtl_uString_assign( pustrPath, strTempPath );
872 if ( strTempPath )
873 rtl_uString_release( strTempPath );
876 OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
879 return nError;
882 /****************************************************************************/
883 /* osl_getSystemPathFromFileURL */
884 /****************************************************************************/
886 oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
888 return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, sal_True );
889 #if 0
890 sal_Int32 nIndex = 0;
891 rtl_uString * pTmp = NULL;
893 sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
895 /* temporary hack: if already system path, return ustrFileURL */
897 if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
899 OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
900 rtl_uString_assign( pustrSystemPath, ustrFileURL );
901 return osl_File_E_None;
905 /* a valid file url may not start with '/' */
906 if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) )
908 return osl_File_E_INVAL;
911 /* search for encoded slashes (%2F) and decode every single token if we find one */
912 if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) )
914 rtl_uString * ustrPathToken = NULL;
915 sal_Int32 nOffset = 7;
919 nOffset += nIndex;
921 /* break url down in '/' devided tokens tokens */
922 nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' );
924 /* copy token to new string */
925 rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset,
926 -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ );
928 /* decode token */
929 rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
931 /* the result should not contain any '/' */
932 if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) )
934 rtl_uString_release( pTmp );
935 rtl_uString_release( ustrPathToken );
937 return osl_File_E_INVAL;
940 } while( -1 != nIndex );
942 /* release temporary string and restore index variable */
943 rtl_uString_release( ustrPathToken );
944 nIndex = 0;
947 /* protocol and server should not be encoded, so decode the whole string */
948 rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
950 /* check if file protocol specified */
951 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
952 if( 7 <= pTmp->length )
954 rtl_uString * pProtocol = NULL;
955 rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 );
957 /* protocol is case insensitive */
958 rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length );
960 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) )
961 nIndex = 7;
963 rtl_uString_release( pProtocol );
966 /* skip "localhost" or "127.0.0.1" if "file://" is specified */
967 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
968 if( nIndex && ( 10 <= pTmp->length - nIndex ) )
970 rtl_uString * pServer = NULL;
971 rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 );
973 /* server is case insensitive */
974 rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length );
976 if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) ||
977 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) )
979 /* don't exclude the '/' */
980 nIndex += 9;
983 rtl_uString_release( pServer );
986 if( nIndex )
987 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex );
989 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
990 if( (sal_Unicode) '~' == pTmp->buffer[0] )
992 /* check if another user is specified */
993 if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) )
995 rtl_uString *pTmp2 = NULL;
997 /* osl_getHomeDir returns file URL */
998 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 );
1000 /* remove "file://" prefix */
1001 rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 );
1003 /* replace '~' in original string */
1004 rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
1005 rtl_uString_release( pTmp2 );
1008 else
1010 /* FIXME: replace ~user with users home directory */
1011 return osl_File_E_INVAL;
1015 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
1017 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
1020 *pustrSystemPath = pTmp;
1021 return osl_File_E_None;
1022 #endif // 0
1026 /****************************************************************************
1027 * osl_getSystemPathFromFileURL_Ex - helper function
1028 * clients may specify if they want to accept relative
1029 * URLs or not
1030 ****************************************************************************/
1032 oslFileError osl_getSystemPathFromFileURL_Ex(
1033 rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
1035 return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, bAllowRelative);
1036 #if 0
1037 rtl_uString* temp = 0;
1038 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
1040 if (osl_File_E_None == osl_error)
1042 if (bAllowRelative
1043 || (UNICHAR_SLASH == temp->buffer[0])
1044 || (UNICHAR_COLON == temp->buffer[1] && UNICHAR_SLASH == temp->buffer[2]))
1046 *pustrSystemPath = temp;
1048 else
1050 rtl_uString_release(temp);
1051 osl_error = osl_File_E_INVAL;
1055 return osl_error;
1056 #endif
1059 namespace /* private */
1062 #if 0 // YD
1064 /******************************************************
1065 * Helper function, return a pinter to the final '\0'
1066 * of a string
1067 ******************************************************/
1069 sal_Unicode* ustrtoend(sal_Unicode* pStr)
1071 return (pStr + rtl_ustr_getLength(pStr));
1074 /*********************************************
1076 ********************************************/
1077 sal_Unicode* ustrcpy(const sal_Unicode* s, sal_Unicode* d)
1079 const sal_Unicode* sc = s;
1080 sal_Unicode* dc = d;
1082 while ((*dc++ = *sc++))
1083 /**/;
1085 return d;
1088 /*********************************************
1090 ********************************************/
1092 sal_Unicode* ustrncpy(const sal_Unicode* s, sal_Unicode* d, unsigned int n)
1094 const sal_Unicode* sc = s;
1095 sal_Unicode* dc = d;
1096 unsigned int i = n;
1098 while (i--)
1099 *dc++ = *sc++;
1101 if (n)
1102 *dc = 0;
1104 return d;
1107 /*********************************************
1109 ********************************************/
1111 sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
1113 sal_Unicode* p = ustrtoend(d);
1114 *p++ = chr;
1115 *p = 0;
1116 return d;
1119 /*********************************************
1121 ********************************************/
1123 sal_Unicode* ustrcat(const sal_Unicode* s, sal_Unicode* d)
1125 sal_Unicode* dc = ustrtoend(d);
1126 ustrcpy(s, dc);
1127 return d;
1130 /******************************************************
1132 ******************************************************/
1134 bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
1136 sal_Unicode* p = ustrtoend(pStr);
1137 if (p > pStr)
1138 p--;
1139 return (*p == Chr);
1142 /******************************************************
1143 * Ensure that the given string has the specified last
1144 * character if necessary append it
1145 ******************************************************/
1147 sal_Unicode* _strensurelast(sal_Unicode* pStr, sal_Unicode Chr)
1149 if (!_islastchr(pStr, Chr))
1150 ustrchrcat(Chr, pStr);
1151 return pStr;
1154 /******************************************************
1155 * Remove the last part of a path, a path that has
1156 * only a '/' or no '/' at all will be returned
1157 * unmodified
1158 ******************************************************/
1160 sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
1162 /* we always may skip -2 because we
1163 may at least stand on a '/' but
1164 either there is no other character
1165 before this '/' or it's another
1166 character than the '/'
1168 sal_Unicode* p = ustrtoend(aPath) - 2;
1170 // move back to the next path separator
1171 // or to the start of the string
1172 while ((p > aPath) && (*p != UNICHAR_SLASH))
1173 p--;
1175 if (p >= aPath)
1177 if (UNICHAR_SLASH == *p)
1179 p++;
1180 *p = '\0';
1182 else
1184 *p = '\0';
1188 return aPath;
1191 /******************************************************
1193 ******************************************************/
1195 oslFileError _osl_resolvepath(
1196 /*inout*/ sal_Unicode* path,
1197 /*inout*/ sal_Unicode* current_pos,
1198 /*in */ sal_Unicode* sentinel,
1199 /*inout*/ bool* failed)
1201 oslFileError ferr = osl_File_E_None;
1203 if (!*failed)
1205 char unresolved_path[PATH_MAX];
1206 if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
1207 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1209 char resolved_path[PATH_MAX];
1210 if (realpath(unresolved_path, resolved_path))
1212 if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
1213 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1215 current_pos = ustrtoend(path) - 1;
1217 else
1219 if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
1220 *failed = true;
1221 else
1222 ferr = oslTranslateFileError(OSL_FET_ERROR, errno);
1226 return ferr;
1229 /******************************************************
1230 * Works even with non existing paths. The resulting
1231 * path must not exceed PATH_MAX else
1232 * osl_File_E_NAMETOOLONG is the result
1233 ******************************************************/
1235 oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path)
1237 // the given unresolved path must not exceed PATH_MAX
1238 if (unresolved_path.getLength() >= (PATH_MAX - 2))
1239 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1241 sal_Unicode path_resolved_so_far[PATH_MAX];
1242 const sal_Unicode* punresolved = unresolved_path.getStr();
1243 sal_Unicode* presolvedsf = path_resolved_so_far;
1245 // reserve space for leading '/' and trailing '\0'
1246 // do not exceed this limit
1247 sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
1249 // if realpath fails with error ENOTDIR, EACCES or ENOENT
1250 // we will not call it again, because _osl_realpath should also
1251 // work with non existing directories etc.
1252 bool realpath_failed = false;
1253 oslFileError ferr;
1255 path_resolved_so_far[0] = '\0';
1257 while (*punresolved != '\0')
1259 // ignore '/.' , skip one part back when '/..'
1261 if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf))
1263 if ('\0' == *(punresolved + 1))
1265 punresolved++;
1266 continue;
1268 else if (UNICHAR_SLASH == *(punresolved + 1))
1270 punresolved += 2;
1271 continue;
1273 else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2))))
1275 _rmlastpathtoken(path_resolved_so_far);
1277 presolvedsf = ustrtoend(path_resolved_so_far) - 1;
1279 if (UNICHAR_SLASH == *(punresolved + 2))
1280 punresolved += 3;
1281 else
1282 punresolved += 2;
1284 continue;
1286 else // a file or directory name may start with '.'
1288 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
1289 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1291 ustrchrcat(*punresolved++, path_resolved_so_far);
1293 if ('\0' == *punresolved && !realpath_failed)
1295 ferr = _osl_resolvepath(
1296 path_resolved_so_far,
1297 presolvedsf,
1298 sentinel,
1299 &realpath_failed);
1301 if (osl_File_E_None != ferr)
1302 return ferr;
1306 else if (UNICHAR_SLASH == *punresolved)
1308 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
1309 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1311 ustrchrcat(*punresolved++, path_resolved_so_far);
1313 if (!realpath_failed)
1315 ferr = _osl_resolvepath(
1316 path_resolved_so_far,
1317 presolvedsf,
1318 sentinel,
1319 &realpath_failed);
1321 if (osl_File_E_None != ferr)
1322 return ferr;
1324 if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH))
1326 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
1327 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1329 ustrchrcat(UNICHAR_SLASH, path_resolved_so_far);
1333 else // any other character
1335 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
1336 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
1338 ustrchrcat(*punresolved++, path_resolved_so_far);
1340 if ('\0' == *punresolved && !realpath_failed)
1342 ferr = _osl_resolvepath(
1343 path_resolved_so_far,
1344 presolvedsf,
1345 sentinel,
1346 &realpath_failed);
1348 if (osl_File_E_None != ferr)
1349 return ferr;
1354 sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
1356 OSL_ASSERT(len < PATH_MAX);
1358 resolved_path = rtl::OUString(path_resolved_so_far, len);
1360 return osl_File_E_None;
1363 #endif // 0 // YD
1365 } // end namespace private
1367 #if OSL_DEBUG_LEVEL > 0
1369 //#####################################################
1370 void _osl_warnFile( const char *message, rtl_uString *ustrFile )
1372 char szBuffer[2048];
1374 if (ustrFile)
1376 rtl_String *strFile = NULL;
1378 rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
1379 snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
1380 rtl_string_release( strFile );
1382 message = szBuffer;
1384 OSL_ENSURE( 0, message );
1387 #endif // OSL_DEBUG_LEVEL > 0
1389 /******************************************************
1390 * osl_getAbsoluteFileURL
1391 ******************************************************/
1393 //oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
1394 oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
1396 oslFileError eError;
1397 rtl_uString *ustrRelSysPath = NULL;
1398 rtl_uString *ustrBaseSysPath = NULL;
1400 if ( ustrBaseURL && ustrBaseURL->length )
1402 eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
1403 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
1405 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
1407 else
1409 eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
1410 OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
1413 if ( !eError )
1415 CHAR szBuffer[_MAX_PATH];
1416 CHAR szRelSysPath[_MAX_PATH];
1417 CHAR szCurrentDir[_MAX_PATH];
1418 int result;
1419 char* cwd;
1420 int rc;
1422 /*@@@ToDo
1423 Bad, bad hack, this only works if the base path
1424 really exists which is not necessary according
1425 to RFC2396
1426 The whole FileURL implementation should be merged
1427 with the rtl/uri class.
1429 if ( ustrBaseSysPath )
1431 CHAR szBaseSysPath[_MAX_PATH];
1433 if (!g_CurrentDirectoryMutex)
1434 g_CurrentDirectoryMutex = osl_createMutex();
1436 osl_acquireMutex( g_CurrentDirectoryMutex );
1438 cwd = getcwd( szCurrentDir, sizeof(szCurrentDir) );
1439 UnicodeToText( szBaseSysPath, sizeof(szBaseSysPath), ustrBaseSysPath->buffer, ustrBaseSysPath->length);
1440 rc = chdir( szBaseSysPath);
1443 UnicodeToText( szRelSysPath, sizeof(szRelSysPath), ustrRelSysPath->buffer, ustrRelSysPath->length);
1444 result = !_abspath( szBuffer, szRelSysPath, sizeof(szBuffer));
1446 if ( ustrBaseSysPath )
1448 rc = chdir( szCurrentDir );
1450 osl_releaseMutex( g_CurrentDirectoryMutex );
1453 if ( result )
1455 rtl_uString *ustrAbsSysPath = NULL;
1457 oslMakeUStrFromPsz( szBuffer, &ustrAbsSysPath);
1459 eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
1461 if ( ustrAbsSysPath )
1462 rtl_uString_release( ustrAbsSysPath );
1464 else
1465 eError = osl_File_E_INVAL;
1468 if ( ustrBaseSysPath )
1469 rtl_uString_release( ustrBaseSysPath );
1471 if ( ustrRelSysPath )
1472 rtl_uString_release( ustrRelSysPath );
1474 return eError;
1475 #if 0
1476 FileBase::RC rc;
1477 rtl::OUString unresolved_path;
1479 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path);
1481 if(FileBase::E_None != rc)
1482 return oslFileError(rc);
1484 if (systemPathIsRelativePath(unresolved_path))
1486 rtl::OUString base_path;
1487 rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False);
1489 if (FileBase::E_None != rc)
1490 return oslFileError(rc);
1492 rtl::OUString abs_path;
1493 systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
1495 unresolved_path = abs_path;
1498 rtl::OUString resolved_path;
1499 rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
1501 if (FileBase::E_None == rc)
1503 rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
1504 OSL_ASSERT(FileBase::E_None == rc);
1507 return oslFileError(rc);
1508 #endif // 0
1512 namespace /* private */
1515 /*********************************************
1516 No separate error code if unicode to text
1517 conversion or getenv fails because for the
1518 caller there is no difference why a file
1519 could not be found in $PATH
1520 ********************************************/
1522 bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
1524 bool bfound = false;
1525 rtl::OUString path = rtl::OUString::createFromAscii("PATH");
1526 rtl::OUString env_path;
1528 if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
1529 bfound = osl::searchPath(file_path, env_path, result);
1531 return bfound;
1534 /*********************************************
1535 No separate error code if unicode to text
1536 conversion or getcwd fails because for the
1537 caller there is no difference why a file
1538 could not be found in CDW
1539 ********************************************/
1541 bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
1543 bool bfound = false;
1544 rtl::OUString cwd_url;
1546 if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
1548 rtl::OUString cwd;
1549 FileBase::getSystemPathFromFileURL(cwd_url, cwd);
1550 bfound = osl::searchPath(file_path, cwd, result);
1552 return bfound;
1555 /*********************************************
1557 ********************************************/
1559 bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
1561 return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
1564 } // end namespace private
1567 /****************************************************************************
1568 * osl_searchFileURL
1569 ***************************************************************************/
1571 oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
1573 OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
1575 FileBase::RC rc;
1576 rtl::OUString file_path;
1578 // try to interpret search path as file url else assume it's a system path list
1579 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
1580 if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
1581 file_path = ustrFilePath;
1582 else if (FileBase::E_None != rc)
1583 return oslFileError(rc);
1585 bool bfound = false;
1586 rtl::OUString result;
1588 if (find_in_searchPath(file_path, ustrSearchPath, result) ||
1589 find_in_PATH(file_path, result) ||
1590 find_in_CWD(file_path, result))
1592 rtl::OUString resolved;
1594 if (osl::realpath(result, resolved))
1596 #if OSL_DEBUG_LEVEL > 0
1597 oslFileError osl_error =
1598 #endif
1599 osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
1600 OSL_ASSERT(osl_File_E_None == osl_error);
1601 bfound = true;
1604 return bfound ? osl_File_E_None : osl_File_E_NOENT;
1608 /****************************************************************************
1609 * FileURLToPath
1610 ***************************************************************************/
1612 oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
1614 rtl_uString* ustrSystemPath = NULL;
1615 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
1617 if(osl_File_E_None != osl_error)
1618 return osl_error;
1620 osl_systemPathRemoveSeparator(ustrSystemPath);
1622 /* convert unicode path to text */
1623 if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
1624 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
1626 rtl_uString_release(ustrSystemPath);
1628 return osl_error;