summaryrefslogtreecommitdiff
path: root/sal/osl/os2/file_url.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/os2/file_url.cxx')
-rw-r--r--sal/osl/os2/file_url.cxx999
1 files changed, 999 insertions, 0 deletions
diff --git a/sal/osl/os2/file_url.cxx b/sal/osl/os2/file_url.cxx
new file mode 100644
index 000000000000..395cfea13e41
--- /dev/null
+++ b/sal/osl/os2/file_url.cxx
@@ -0,0 +1,999 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <ctype.h>
+#include "system.h"
+
+#include <limits.h>
+
+#include <errno.h>
+
+#include <stdlib.h>
+
+#include <strings.h>
+
+#include <unistd.h>
+#include <osl/file.h>
+#include <osl/security.h>
+#include <rtl/uri.h>
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.h>
+
+#include <osl/thread.h>
+#include <osl/file.hxx>
+#include <osl/mutex.h>
+#include <osl/process.h>
+#include "file_error_transl.h"
+
+#include "file_url.h"
+#include <sal/macros.h>
+#include "file_path_helper.hxx"
+
+#include "uunxapi.hxx"
+
+#include <wchar.h>
+#include <wctype.h>
+
+/***************************************************
+
+ General note
+
+ This file contains the part that handles File URLs.
+
+ File URLs as scheme specific notion of URIs
+ (RFC2396) may be handled platform independend, but
+ will not in osl which is considered wrong.
+ Future version of osl should handle File URLs this
+ way. In rtl/uri there is already an URI parser etc.
+ so this code should be consolidated.
+
+ **************************************************/
+
+oslMutex g_CurrentDirectoryMutex;
+
+
+/***************************************************
+ * forward
+ **************************************************/
+
+void _osl_warnFile(const char*, rtl_uString*);
+rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr);
+
+extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
+extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
+
+/***************************************************
+ * namespace directives
+ **************************************************/
+
+using namespace osl;
+
+/******************************************************************************
+ *
+ * Exported Module Functions
+ *
+ *****************************************************************************/
+
+/* a slightly modified version of Pchar in rtl/source/uri.c */
+const sal_Bool uriCharClass[128] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
+};
+
+
+/* check for top wrong usage strings */
+/*
+static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
+{
+ rtl_uString *pTmp = NULL;
+ sal_Bool bRet;
+
+ rtl_uString_newFromStr_WithLength( &pTmp, path, len );
+
+ rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
+
+ bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
+
+ rtl_uString_release( pTmp );
+ return bRet;
+}
+*/
+
+
+/****************************************************************************/
+/* osl_getFileURLFromSystemPath */
+/****************************************************************************/
+
+BOOL WINAPI IsValidFilePathComponent(
+ LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
+{
+ LPCTSTR lpComponentEnd = NULL;
+ LPCTSTR lpCurrent = lpComponent;
+ BOOL fValid = TRUE; /* Assume success */
+ TCHAR cLast = 0;
+
+ /* Path component length must not exceed MAX_PATH */
+
+ while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < _MAX_PATH )
+ {
+ switch ( *lpCurrent )
+ {
+ /* Both backslash and slash determine the end of a path component */
+ case '\0':
+ case '/':
+ case '\\':
+ switch ( cLast )
+ {
+ /* Component must not end with '.' or blank and can't be empty */
+
+ case '.':
+ if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
+ {
+ if ( 1 == lpCurrent - lpComponent )
+ {
+ /* Current directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
+ {
+ /* Parent directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ }
+ case 0:
+ case ' ':
+ lpComponentEnd = lpCurrent - 1;
+ fValid = FALSE;
+ break;
+ default:
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ break;
+ /* '?' and '*' are valid wildcards but not valid file name characters */
+ case '?':
+ case '*':
+ if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
+ break;
+ /* The following characters are reserved */
+ case '<':
+ case '>':
+ case '\"':
+ case '|':
+ case ':':
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ break;
+ default:
+ /* Characters below ASCII 32 are not allowed */
+ if ( *lpCurrent < ' ' )
+ {
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ }
+ break;
+ }
+ cLast = *lpCurrent++;
+ }
+
+ /* If we don't reached the end of the component the length of the component was to long
+ ( See condition of while loop ) */
+ if ( !lpComponentEnd )
+ {
+ fValid = FALSE;
+ lpComponentEnd = lpCurrent;
+ }
+
+ /* Test wether the component specifies a device name what is not allowed */
+
+ // MT: PERFORMANCE:
+ // This is very expensive. A lot of calls to _tcsicmp.
+ // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
+ // Possible optimizations
+ // - Array should be const static
+ // - Sorted array, use binary search
+ // - More intelligent check for com1-9, lpt1-9
+ // Maybe make szComponent upper case, don't search case intensitive
+ // 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.
+ /*
+ if ( fValid )
+ {
+ LPCTSTR alpDeviceNames[] =
+ {
+ TEXT("CON"),
+ TEXT("PRN"),
+ TEXT("AUX"),
+ TEXT("CLOCK$"),
+ TEXT("NUL"),
+ TEXT("LPT1"),
+ TEXT("LPT2"),
+ TEXT("LPT3"),
+ TEXT("LPT4"),
+ TEXT("LPT5"),
+ TEXT("LPT6"),
+ TEXT("LPT7"),
+ TEXT("LPT8"),
+ TEXT("LPT9"),
+ TEXT("COM1"),
+ TEXT("COM2"),
+ TEXT("COM3"),
+ TEXT("COM4"),
+ TEXT("COM5"),
+ TEXT("COM6"),
+ TEXT("COM7"),
+ TEXT("COM8"),
+ TEXT("COM9")
+ };
+
+ TCHAR szComponent[MAX_PATH];
+ int nComponentLength;
+ LPCTSTR lpDot;
+ int i;
+
+ // A device name with an extension is also invalid
+ lpDot = _tcschr( lpComponent, '.' );
+
+ if ( !lpDot || lpDot > lpComponentEnd )
+ nComponentLength = lpComponentEnd - lpComponent;
+ else
+ nComponentLength = lpDot - lpComponent;
+
+ _tcsncpy( szComponent, lpComponent, nComponentLength );
+ szComponent[nComponentLength] = 0;
+
+ for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
+ {
+ if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
+ {
+ lpComponentEnd = lpComponent;
+ fValid = FALSE;
+ break;
+ }
+ }
+ }
+ */
+
+ if ( fValid )
+ {
+ // Empty components are not allowed
+ if ( lpComponentEnd - lpComponent < 1 )
+ fValid = FALSE;
+
+ // If we reached the end of the string NULL is returned
+ else if ( !*lpComponentEnd )
+ lpComponentEnd = NULL;
+
+ }
+
+ if ( lppComponentEnd )
+ *lppComponentEnd = lpComponentEnd;
+
+ return fValid;
+}
+
+//#####################################################
+DWORD WINAPI IsValidFilePath(LPCTSTR lpszPath, LPCTSTR *lppError, DWORD dwFlags)
+{
+ LPCTSTR lpComponent;
+ BOOL fValid = TRUE;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
+
+ if ( !lpszPath )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Test for UNC path notation */
+ if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
+ {
+ /* Place the pointer behind the leading to backslashes */
+
+ lpComponent = lpszPath + 2;
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
+
+ /* So far we have a valid servername. Now let's see if we also have a network resource */
+
+ dwPathType = PATHTYPE_ABSOLUTE_UNC;
+
+ if ( fValid )
+ {
+ if ( lpComponent && !*++lpComponent )
+ lpComponent = NULL;
+
+ if ( !lpComponent )
+ {
+ dwPathType |= PATHTYPE_IS_SERVER;
+ }
+ else
+ {
+ /* Now test the network resource */
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
+
+ /* If we now reached the end of the path, everything is O.K. */
+
+
+ if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ }
+ }
+
+ /* Local path verification. Must start with <drive>: */
+ else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
+ {
+ /* Place pointer behind correct drive specification */
+
+ lpComponent = lpszPath + 2;
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ lpComponent++;
+ else if ( *lpComponent )
+ fValid = FALSE;
+
+ dwPathType = PATHTYPE_ABSOLUTE_LOCAL;
+
+ /* Now we are behind the backslash or it was a simple drive without backslash */
+
+ if ( fValid && !*lpComponent )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+
+ /* Can be a relative path */
+ else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ {
+ lpComponent = lpszPath;
+
+ /* Relative path can start with a backslash */
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ {
+ lpComponent++;
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+
+ dwPathType = PATHTYPE_RELATIVE;
+ }
+
+ /* Anything else is an error */
+ else
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Now validate each component of the path */
+ while ( fValid && lpComponent )
+ {
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
+
+ if ( fValid && lpComponent )
+ {
+ lpComponent++;
+
+ /* If the string behind the backslash is empty, we've done */
+
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+ }
+
+ if ( fValid && _tcslen( lpszPath ) >= _MAX_PATH )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath + _MAX_PATH;
+ }
+
+ if ( lppError )
+ *lppError = lpComponent;
+
+ return fValid ? dwPathType : PATHTYPE_ERROR;
+}
+
+sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
+{
+ sal_Char *pBuffer;
+ const sal_Char *pSrcEnd;
+ const sal_Char *pSrc;
+ sal_Char *pDest;
+ sal_Int32 nSrcLen;
+ sal_Bool bValidEncoded = sal_True; /* Assume success */
+
+ /* The resulting decoded string length is shorter or equal to the source length */
+
+ nSrcLen = rtl_string_getLength(strUTF8);
+ pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
+
+ pDest = pBuffer;
+ pSrc = rtl_string_getStr(strUTF8);
+ pSrcEnd = pSrc + nSrcLen;
+
+ /* Now decode the URL what should result in an UTF8 string */
+ while ( bValidEncoded && pSrc < pSrcEnd )
+ {
+ switch ( *pSrc )
+ {
+ case '%':
+ {
+ sal_Char aToken[3];
+ sal_Char aChar;
+
+ pSrc++;
+ aToken[0] = *pSrc++;
+ aToken[1] = *pSrc++;
+ aToken[2] = 0;
+
+ aChar = (sal_Char)strtoul( aToken, NULL, 16 );
+
+ /* The chars are path delimiters and must not be encoded */
+
+ if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
+ bValidEncoded = sal_False;
+ else
+ *pDest++ = aChar;
+ }
+ break;
+ default:
+ *pDest++ = *pSrc++;
+ break;
+ }
+ }
+
+ *pDest++ = 0;
+
+ if ( bValidEncoded ) {
+ rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrDecodedURL != 0);
+ }
+
+ rtl_freeMemory( pBuffer );
+
+ return bValidEncoded;
+}
+
+//#############################################
+void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
+{
+ /* Encode non ascii characters within the URL */
+
+ rtl_String *strUTF8 = NULL;
+ sal_Char *pszEncodedURL;
+ const sal_Char *pURLScan;
+ sal_Char *pURLDest;
+ sal_Int32 nURLScanLen;
+ sal_Int32 nURLScanCount;
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
+
+ pURLDest = pszEncodedURL;
+ pURLScan = rtl_string_getStr( strUTF8 );
+ nURLScanLen = rtl_string_getLength( strUTF8 );
+ nURLScanCount = 0;
+
+ while ( nURLScanCount < nURLScanLen )
+ {
+ sal_Char cCurrent = *pURLScan;
+
+ switch ( cCurrent )
+ {
+ default:
+ if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
+ {
+ sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
+ pURLDest += 3;
+ break;
+ }
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case '$':
+ case '&':
+ case '+':
+ case ',':
+ case '=':
+ case '@':
+ case ':':
+ case '/':
+ case '\\':
+ case '|':
+ *pURLDest++ = cCurrent;
+ break;
+ case 0:
+ break;
+ }
+
+ pURLScan++;
+ nURLScanCount++;
+ }
+
+
+ *pURLDest = 0;
+
+ rtl_string_release( strUTF8 );
+ rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
+ rtl_freeMemory( pszEncodedURL );
+}
+
+//#############################################
+oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
+{
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+ rtl_uString *strTempURL = NULL;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if (strPath)
+ dwPathType = IsValidFilePath(strPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE);
+
+ if (dwPathType)
+ {
+ rtl_uString *strTempPath = NULL;
+
+ /* Replace backslashes */
+
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_RELATIVE:
+ rtl_uString_assign( &strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_UNC:
+ rtl_uString_newFromAscii( &strTempURL, "file:" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ rtl_uString_newFromAscii( &strTempURL, "file:///" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ default:
+ break;
+ }
+
+ /* Release temp path */
+
+ rtl_uString_release( strTempPath );
+ }
+
+ if ( osl_File_E_None == nError )
+ {
+ rtl_String *strEncodedURL = NULL;
+
+ /* Encode the URL */
+
+ _osl_encodeURL( strTempURL, &strEncodedURL );
+
+ /* Provide URL via unicode string */
+
+ rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrURL != 0);
+ rtl_string_release( strEncodedURL );
+ }
+
+ /* Release temp URL */
+
+ if ( strTempURL )
+ rtl_uString_release( strTempURL );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
+ */
+
+ return nError;
+}
+
+oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
+{
+ return _osl_getFileURLFromSystemPath( ustrSystemPath, pustrFileURL );
+}
+
+//#############################################
+oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
+{
+ rtl_String *strUTF8 = NULL;
+ rtl_uString *strDecodedURL = NULL;
+ rtl_uString *strTempPath = NULL;
+ const sal_Unicode *pDecodedURL;
+ sal_uInt32 nDecodedLen;
+ sal_Bool bValidEncoded;
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+
+ /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
+ having a mixed encoded URL later */
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
+
+ OSL_ENSURE_FILE(
+ strUTF8->length == strURL->length ||
+ 0 != rtl_ustr_ascii_shortenedCompare_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
+ ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
+
+ bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
+
+ /* Release the encoded UTF8 string */
+
+ rtl_string_release( strUTF8 );
+
+
+ if ( bValidEncoded )
+ {
+ /* Replace backslashes and pipes */
+
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
+
+ pDecodedURL = rtl_uString_getStr( strDecodedURL );
+ nDecodedLen = rtl_uString_getLength( strDecodedURL );
+
+ /* Must start with "file://" */
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
+ {
+ sal_uInt32 nSkip;
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
+ nSkip = 8;
+ else if (
+ 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
+ 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
+ )
+ nSkip = 17;
+ else
+ nSkip = 5;
+
+ /* Indicates local root */
+ if ( nDecodedLen == nSkip )
+ rtl_uString_newFromStr_WithLength( &strTempPath, (const sal_Unicode*)WSTR_SYSTEM_ROOT_PATH, SAL_N_ELEMENTS(WSTR_SYSTEM_ROOT_PATH) - 1 );
+ else
+ rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
+
+ if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_ELLIPSE ) )
+ nError = osl_File_E_None;
+ }
+ else if ( bAllowRelative ) /* This maybe a relative file URL */
+ {
+ rtl_uString_assign( &strTempPath, strDecodedURL );
+
+ if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE ) )
+ nError = osl_File_E_None;
+ }
+ /*
+ else
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
+ */
+
+ }
+
+ if ( strDecodedURL )
+ rtl_uString_release( strDecodedURL );
+
+ if ( osl_File_E_None == nError )
+ rtl_uString_assign( pustrPath, strTempPath );
+
+ if ( strTempPath )
+ rtl_uString_release( strTempPath );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
+ */
+
+ return nError;
+}
+
+/****************************************************************************/
+/* osl_getSystemPathFromFileURL */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
+{
+ return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, sal_True );
+}
+
+
+/****************************************************************************
+ * osl_getSystemPathFromFileURL_Ex - helper function
+ * clients may specify if they want to accept relative
+ * URLs or not
+ ****************************************************************************/
+
+oslFileError osl_getSystemPathFromFileURL_Ex(
+ rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
+{
+ return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, bAllowRelative);
+}
+
+
+#if OSL_DEBUG_LEVEL > 0
+
+ //#####################################################
+ void _osl_warnFile( const char *message, rtl_uString *ustrFile )
+ {
+ char szBuffer[2048];
+
+ if (ustrFile)
+ {
+ rtl_String *strFile = NULL;
+
+ rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
+ rtl_string_release( strFile );
+
+ message = szBuffer;
+ }
+ OSL_ENSURE( 0, message );
+ }
+
+#endif // OSL_DEBUG_LEVEL > 0
+
+/******************************************************
+ * osl_getAbsoluteFileURL
+ ******************************************************/
+
+//oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
+oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
+{
+ oslFileError eError;
+ rtl_uString *ustrRelSysPath = NULL;
+ rtl_uString *ustrBaseSysPath = NULL;
+
+ if ( ustrBaseURL && ustrBaseURL->length )
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
+
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
+ }
+ else
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
+ }
+
+ if ( !eError )
+ {
+ CHAR szBuffer[_MAX_PATH];
+ CHAR szRelSysPath[_MAX_PATH];
+ CHAR szCurrentDir[_MAX_PATH];
+ int result;
+ char* cwd;
+ int rc;
+
+/*@@@ToDo
+ Bad, bad hack, this only works if the base path
+ really exists which is not necessary according
+ to RFC2396
+ The whole FileURL implementation should be merged
+ with the rtl/uri class.
+*/
+ if ( ustrBaseSysPath )
+ {
+ CHAR szBaseSysPath[_MAX_PATH];
+
+ if (!g_CurrentDirectoryMutex)
+ g_CurrentDirectoryMutex = osl_createMutex();
+
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+
+ cwd = getcwd( szCurrentDir, sizeof(szCurrentDir) );
+ UnicodeToText( szBaseSysPath, sizeof(szBaseSysPath), ustrBaseSysPath->buffer, ustrBaseSysPath->length);
+ rc = chdir( szBaseSysPath);
+ }
+
+ UnicodeToText( szRelSysPath, sizeof(szRelSysPath), ustrRelSysPath->buffer, ustrRelSysPath->length);
+ result = !_abspath( szBuffer, szRelSysPath, sizeof(szBuffer));
+
+ if ( ustrBaseSysPath )
+ {
+ rc = chdir( szCurrentDir );
+
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+ }
+
+ if ( result )
+ {
+ rtl_uString *ustrAbsSysPath = NULL;
+
+ oslMakeUStrFromPsz( szBuffer, &ustrAbsSysPath);
+
+ eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
+
+ if ( ustrAbsSysPath )
+ rtl_uString_release( ustrAbsSysPath );
+ }
+ else
+ eError = osl_File_E_INVAL;
+ }
+
+ if ( ustrBaseSysPath )
+ rtl_uString_release( ustrBaseSysPath );
+
+ if ( ustrRelSysPath )
+ rtl_uString_release( ustrRelSysPath );
+
+ return eError;
+}
+
+
+namespace /* private */
+{
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getenv fails because for the
+ caller there is no difference why a file
+ could not be found in $PATH
+ ********************************************/
+
+ bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString path = rtl::OUString::createFromAscii("PATH");
+ rtl::OUString env_path;
+
+ if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
+ bfound = osl::searchPath(file_path, env_path, result);
+
+ return bfound;
+ }
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getcwd fails because for the
+ caller there is no difference why a file
+ could not be found in CDW
+ ********************************************/
+
+ bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString cwd_url;
+
+ if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
+ {
+ rtl::OUString cwd;
+ FileBase::getSystemPathFromFileURL(cwd_url, cwd);
+ bfound = osl::searchPath(file_path, cwd, result);
+ }
+ return bfound;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
+ {
+ return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
+ }
+
+} // end namespace private
+
+
+/****************************************************************************
+ * osl_searchFileURL
+ ***************************************************************************/
+
+oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
+{
+ OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
+
+ FileBase::RC rc;
+ rtl::OUString file_path;
+
+ // try to interpret search path as file url else assume it's a system path list
+ rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
+ if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
+ file_path = ustrFilePath;
+ else if (FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ bool bfound = false;
+ rtl::OUString result;
+
+ if (find_in_searchPath(file_path, ustrSearchPath, result) ||
+ find_in_PATH(file_path, result) ||
+ find_in_CWD(file_path, result))
+ {
+ rtl::OUString resolved;
+
+ if (osl::realpath(result, resolved))
+ {
+#if OSL_DEBUG_LEVEL > 0
+ oslFileError osl_error =
+#endif
+ osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
+ OSL_ASSERT(osl_File_E_None == osl_error);
+ bfound = true;
+ }
+ }
+ return bfound ? osl_File_E_None : osl_File_E_NOENT;
+}
+
+
+/****************************************************************************
+ * FileURLToPath
+ ***************************************************************************/
+
+oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
+
+ if(osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ /* convert unicode path to text */
+ if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
+ osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ rtl_uString_release(ustrSystemPath);
+
+ return osl_error;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */