diff options
-rw-r--r-- | sal/osl/unx/file_url.cxx | 209 | ||||
-rw-r--r-- | sal/osl/w32/file_url.cxx | 5 | ||||
-rw-r--r-- | sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx | 282 |
3 files changed, 132 insertions, 364 deletions
diff --git a/sal/osl/unx/file_url.cxx b/sal/osl/unx/file_url.cxx index b58251577d43..16b3532c878e 100644 --- a/sal/osl/unx/file_url.cxx +++ b/sal/osl/unx/file_url.cxx @@ -37,12 +37,12 @@ #include <unistd.h> #include "osl/file.hxx" -#include <osl/security.hxx> +#include <osl/security.h> #include <osl/diagnose.h> #include <osl/thread.h> #include <osl/process.h> -#include <rtl/uri.hxx> +#include <rtl/uri.h> #include <rtl/ustring.hxx> #include <rtl/ustrbuf.h> #include "rtl/textcvt.h" @@ -146,99 +146,154 @@ oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uStrin /* osl_getSystemPathFromFileURL */ /****************************************************************************/ -namespace { - -oslFileError getSystemPathFromFileUrl( - rtl::OUString const & url, rtl::OUString * path, bool homeAbbreviation) +oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath ) { + sal_Int32 nIndex; + rtl_uString * pTmp = NULL; + + sal_Unicode encodedSlash[3] = { '%', '2', 'F' }; + sal_Unicode protocolDelimiter[3] = { ':', '/', '/' }; + OSL_ASSERT(path != 0 && path->isEmpty()); - sal_Unicode const * p = url.getStr(); - sal_Unicode const * end = p + url.getLength(); + /* temporary hack: if already system path, return ustrFileURL */ + /* + if( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) + { + OSL_FAIL( "osl_getSystemPathFromFileURL: input is already system path" ); + rtl_uString_assign( pustrSystemPath, ustrFileURL ); + return osl_File_E_None; + } + */ /* a valid file url may not start with '/' */ - if ((p == end) || (*p == UNICHAR_SLASH)) + if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) ) + { return osl_File_E_INVAL; + } - for (sal_Unicode const * p1 = p; p1 != end; ++p1) { - if (*p1 == '?' || *p1 == '#' || - (*p1 == '%' && end - p1 >= 3 && p1[1] == '2' && - (p1[2] == 'F' || p1[2] == 'f'))) + /* Check for non file:// protocols */ + + nIndex = rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, protocolDelimiter, 3 ); + if ( -1 != nIndex && (4 != nIndex || 0 != rtl_ustr_ascii_shortenedCompare_WithLength( ustrFileURL->buffer, ustrFileURL->length,"file", 4 ) ) ) + { + return osl_File_E_INVAL; + } + + /* search for encoded slashes (%2F) and decode every single token if we find one */ + + nIndex = 0; + + if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) ) + { + rtl_uString * ustrPathToken = NULL; + sal_Int32 nOffset = 7; + + do { - return osl_File_E_INVAL; - } + nOffset += nIndex; + + /* break url down in '/' devided tokens tokens */ + nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' ); + + /* copy token to new string */ + rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset, + -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ ); + + /* decode token */ + rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); + + /* the result should not contain any '/' */ + if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) ) + { + rtl_uString_release( pTmp ); + rtl_uString_release( ustrPathToken ); + + return osl_File_E_INVAL; + } + + } while( -1 != nIndex ); + + /* release temporary string and restore index variable */ + rtl_uString_release( ustrPathToken ); + nIndex = 0; } - sal_Unicode const * p1 = p; - while (p1 != end && *p1 != ':' && *p1 != '/') { - ++p1; + + /* protocol and server should not be encoded, so decode the whole string */ + rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); + + /* check if file protocol specified */ + /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ + if( 7 <= pTmp->length ) + { + rtl_uString * pProtocol = NULL; + rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 ); + + /* protocol is case insensitive */ + rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length ); + + if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) ) + nIndex = 7; + + rtl_uString_release( pProtocol ); } - if (p1 != end && *p1 == ':') { - if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths( - p, p1 - p, RTL_CONSTASCII_STRINGPARAM("file")) != - 0) + + /* skip "localhost" or "127.0.0.1" if "file://" is specified */ + /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ + if( nIndex && ( 10 <= pTmp->length - nIndex ) ) + { + rtl_uString * pServer = NULL; + rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 ); + + /* server is case insensitive */ + rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length ); + + if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) || + ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) ) { - return osl_File_E_INVAL; + /* don't exclude the '/' */ + nIndex += 9; } - p = p1 + 1; + + rtl_uString_release( pServer ); } - if (end - p >= 2 && p[0] == '/' && p[1] == '/') { - p += 2; - sal_Int32 i = rtl_ustr_indexOfChar_WithLength(p, end - p, '/'); - p1 = i < 0 ? end : p + i; - if (p1 != p && - (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths( - p, p1 - p, RTL_CONSTASCII_STRINGPARAM("localhost")) != - 0) && - rtl_ustr_ascii_compare_WithLength(p, p1 - p, "127.0.0.1") != 0) + + if( nIndex ) + rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex ); + + /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ + if( (sal_Unicode) '~' == pTmp->buffer[0] ) + { + /* check if another user is specified */ + if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) ) { - return osl_File_E_INVAL; - } - p = p1; - if (p == end) { - *path = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); - return osl_File_E_None; + rtl_uString *pTmp2 = NULL; + + /* osl_getHomeDir returns file URL */ + osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 ); + + /* remove "file://" prefix */ + rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 ); + + /* replace '~' in original string */ + rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 ); + rtl_uString_release( pTmp2 ); } - } - if (homeAbbreviation && end - p >= 2 && p[0] == '/' && p[1] == '~') { - p += 2; - sal_Int32 i = rtl_ustr_indexOfChar_WithLength(p, end - p, '/'); - p1 = i < 0 ? end : p + i; - if (p1 == p) { - rtl::OUString home; - if (!osl::Security().getHomeDir(home)) { - return osl_File_E_INVAL; - } - oslFileError e = getSystemPathFromFileUrl(home, path, false); - if (e != osl_File_E_None) { - return e; - } - } else { - return osl_File_E_INVAL; //TODO + + else + { + /* FIXME: replace ~user with users home directory */ + return osl_File_E_INVAL; } - p = p1; } - rtl::OUString d( - rtl::Uri::decode( - rtl::OUString(p, end - p), rtl_UriDecodeWithCharset, - RTL_TEXTENCODING_UTF8)); - if (d.indexOf(0) >=0) { - return osl_File_E_INVAL; - } - *path += d; - return osl_File_E_None; -} -} -oslFileError osl_getSystemPathFromFileURL( - rtl_uString * pustrFileURL, rtl_uString ** ppustrSystemPath) -{ - rtl::OUString p; - oslFileError e = getSystemPathFromFileUrl( - rtl::OUString(pustrFileURL), &p, true); - if (e == osl_File_E_None) { - rtl_uString_assign(ppustrSystemPath, p.pData); - } - return e; + /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */ + /* + OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) ); + */ + + *pustrSystemPath = pTmp; + return osl_File_E_None; } /****************************************************************************/ diff --git a/sal/osl/w32/file_url.cxx b/sal/osl/w32/file_url.cxx index d6e74a2f4801..ab8593dd0699 100644 --- a/sal/osl/w32/file_url.cxx +++ b/sal/osl/w32/file_url.cxx @@ -601,11 +601,6 @@ static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedUR { switch ( *pSrc ) { - case 0: - case '?': - case '#': - bValidEncoded = false; - break; case '%': { sal_Char aToken[3]; diff --git a/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx b/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx deleted file mode 100644 index e346ebc7a2d1..000000000000 --- a/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx +++ /dev/null @@ -1,282 +0,0 @@ -/* -*- 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, 2011 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 <sal/types.h> -#include "cppunit/TestAssert.h" -#include "cppunit/TestFixture.h" -#include "cppunit/extensions/HelperMacros.h" -#include "cppunit/plugin/TestPlugIn.h" -#include "osl/file.hxx" - -#if defined WNT -#define MY_PATH_IN "/c:/foo/bar" -#define MY_PATH_OUT "c:\\foo\\bar" -#define MY_PATH_OUT_CONT MY_PATH_OUT "\\" -#define MY_PATH_OUT_REL "foo\\bar" -#else -#define MY_PATH_IN "/foo/bar" -#define MY_PATH_OUT MY_PATH_IN -#define MY_PATH_OUT_CONT MY_PATH_OUT "/" -#define MY_PATH_OUT_REL "foo/bar" -#endif - -namespace { - -class Test: public CppUnit::TestFixture { -private: - CPPUNIT_TEST_SUITE(Test); - CPPUNIT_TEST(testBadScheme); - CPPUNIT_TEST(testNoScheme); - CPPUNIT_TEST(testBadAuthority); - CPPUNIT_TEST(testLocalhost1Authority); - CPPUNIT_TEST(testLocalhost2Authority); - CPPUNIT_TEST(testLocalhost3Authority); - CPPUNIT_TEST(testNoAuthority); - CPPUNIT_TEST(testEmptyPath); - CPPUNIT_TEST(testHomeAbbreviation); - CPPUNIT_TEST(testOtherHomeAbbreviation); - CPPUNIT_TEST(testRelative); - CPPUNIT_TEST(testEscape); - CPPUNIT_TEST(testBadEscape2f); - CPPUNIT_TEST(testBadEscape2F); - CPPUNIT_TEST(testBad0); - CPPUNIT_TEST(testBadEscape0); - CPPUNIT_TEST(testBadQuery); - CPPUNIT_TEST(testBadFragment); - CPPUNIT_TEST_SUITE_END(); - - void testBadScheme(); - void testNoScheme(); - void testBadAuthority(); - void testLocalhost1Authority(); - void testLocalhost2Authority(); - void testLocalhost3Authority(); - void testNoAuthority(); - void testEmptyPath(); - void testHomeAbbreviation(); - void testOtherHomeAbbreviation(); - void testRelative(); - void testEscape(); - void testBadEscape2f(); - void testBadEscape2F(); - void testBad0(); - void testBadEscape0(); - void testBadQuery(); - void testBadFragment(); -}; - -void Test::testBadScheme() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo:bar")), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testNoScheme() { -#if !defined WNT //TODO - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("//" MY_PATH_IN)), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT)), p); -#endif -} - -void Test::testBadAuthority() { -#if defined UNX - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://baz" MY_PATH_IN)), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -#endif -} - -void Test::testLocalhost1Authority() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://localhost" MY_PATH_IN)), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT)), p); -} - -void Test::testLocalhost2Authority() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://LOCALHOST" MY_PATH_IN)), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT)), p); -} - -void Test::testLocalhost3Authority() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://127.0.0.1" MY_PATH_IN)), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT)), p); -} - -void Test::testNoAuthority() { -#if !defined WNT //TODO - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_IN)), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT)), p); -#endif -} - -void Test::testEmptyPath() { -#if defined UNX - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://")), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), p); -#endif -} - -void Test::testHomeAbbreviation() { -#if defined UNX - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file:///~" MY_PATH_IN)), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - // could theoretically fail due to osl::Security::getHomeDir problem - CPPUNIT_ASSERT(p.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(MY_PATH_OUT))); -#endif -} - -void Test::testOtherHomeAbbreviation() { -#if defined UNX - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file:///~baz" MY_PATH_IN)), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); // not supported for now - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -#endif -} - -void Test::testRelative() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo/bar")), p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT( - p.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(MY_PATH_OUT_REL))); -} - -void Test::testEscape() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b%61z")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e); - CPPUNIT_ASSERT_EQUAL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_PATH_OUT_CONT "baz")), p); -} - -void Test::testBadEscape2f() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b%2fz")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testBadEscape2F() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b%2Fz")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testBad0() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b\x00z")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testBadEscape0() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b%00z")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testBadQuery() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "?baz")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -void Test::testBadFragment() { - rtl::OUString p; - osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "#baz")), - p); - CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); - CPPUNIT_ASSERT_EQUAL(rtl::OUString(), p); -} - -CPPUNIT_TEST_SUITE_REGISTRATION(Test); - -} - -CPPUNIT_PLUGIN_IMPLEMENT(); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |