summaryrefslogtreecommitdiff
path: root/sal/osl
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2015-11-04 08:01:13 +0100
committerStephan Bergmann <sbergman@redhat.com>2015-11-04 08:06:00 +0100
commit62dbe2e6eb30660f252b4e2c048f4aecf28e41c6 (patch)
tree9813494969a44c60316aec9af2ac10c41ef1e798 /sal/osl
parentc5fefe46fc9dca3942b2fc33ffd1f7e041d450e6 (diff)
Clean up osl_getSystemPathFromFileURL implementation
Change-Id: I2daa355c4a46c4edc73c30185f2b31852351c45f
Diffstat (limited to 'sal/osl')
-rw-r--r--sal/osl/unx/file_url.cxx216
1 files changed, 97 insertions, 119 deletions
diff --git a/sal/osl/unx/file_url.cxx b/sal/osl/unx/file_url.cxx
index 1d8c1fd0314b..c0cbe5bc4741 100644
--- a/sal/osl/unx/file_url.cxx
+++ b/sal/osl/unx/file_url.cxx
@@ -21,22 +21,25 @@
#include "system.hxx"
+#include <cassert>
#include <limits.h>
#include <errno.h>
#include <strings.h>
#include <unistd.h>
#include "osl/file.hxx"
-#include <osl/security.h>
+#include <osl/security.hxx>
#include <osl/diagnose.h>
#include <osl/thread.h>
#include <osl/process.h>
#include <rtl/character.hxx>
#include <rtl/uri.h>
+#include <rtl/uri.hxx>
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.h>
#include "rtl/textcvt.h"
+#include <sal/log.hxx>
#include "file_error_transl.hxx"
#include "file_path_helper.hxx"
@@ -81,36 +84,35 @@ oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uStrin
return osl_File_E_None;
}
-oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
-{
- sal_Int32 nIndex;
- rtl_uString * pTmp = NULL;
-
- sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
+namespace {
+oslFileError getSystemPathFromFileUrl(
+ OUString const & url, OUString * path, bool resolveHome)
+{
+ assert(path != nullptr);
// For compatibility with assumptions in other parts of the code base,
// assume that anything starting with a slash is a system path instead of a
// (relative) file URL (except if it starts with two slashes, in which case
// it is a relative URL with an authority component):
- if (ustrFileURL->length == 0
- || (ustrFileURL->buffer[0] == '/'
- && (ustrFileURL->length == 1 || ustrFileURL->buffer[1] != '/')))
+ if (url.isEmpty()
+ || (url[0] == '/' && (url.getLength() == 1 || url[1] != '/')))
{
return osl_File_E_INVAL;
}
-
// Check for non file scheme:
- if (rtl::isAsciiAlpha(ustrFileURL->buffer[0])) {
- for (sal_Int32 i = 1; i != ustrFileURL->length; ++i) {
- auto c = ustrFileURL->buffer[i];
+ sal_Int32 i = 0;
+ if (rtl::isAsciiAlpha(url[0])) {
+ for (sal_Int32 j = 1; j != url.getLength(); ++j) {
+ auto c = url[j];
if (c == ':') {
if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
- ustrFileURL->buffer, i,
+ url.pData->buffer, j,
RTL_CONSTASCII_STRINGPARAM("file"))
!= 0)
{
return osl_File_E_INVAL;
}
+ i = j + 1;
break;
} else if (!rtl::isAsciiAlphanumeric(c) && c != '+' && c != '-'
&& c != '.')
@@ -119,121 +121,97 @@ oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rt
}
}
}
-
- /* 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
- {
- nOffset += nIndex;
-
- /* break url down in '/' divided tokens tokens */
- nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, '/' );
-
- /* 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, '/' ) )
- {
- 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;
- }
-
- /* 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 );
+ // Handle query or fragment:
+ if (url.indexOf('?', i) != -1 || url.indexOf('#', i) != -1) {
+ return osl_File_E_INVAL;
}
-
- /* 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 ) ) )
+ // Handle authority:
+ if (url.getLength() - i >= 2 && url[i] == '/' && url[i + 1] == '/') {
+ i += 2;
+ sal_Int32 j = url.indexOf('/', i);
+ if (j == -1) {
+ j = url.getLength();
+ }
+ if (j != i
+ && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
+ url.pData->buffer + i, j - i,
+ RTL_CONSTASCII_STRINGPARAM("localhost"))
+ != 0)
+ && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
+ url.pData->buffer + i, j - i,
+ RTL_CONSTASCII_STRINGPARAM("127.0.0.1"))
+ != 0))
{
- /* don't exclude the '/' */
- nIndex += 9;
+ return osl_File_E_INVAL;
}
-
- rtl_uString_release( pServer );
+ i = j;
}
-
- 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( '~' == pTmp->buffer[0] )
- {
- /* check if another user is specified */
- if( ( 1 == pTmp->length ) || ( '/' == pTmp->buffer[1] ) )
- {
- rtl_uString *pTmp2 = NULL;
-
- /* osl_getHomeDir returns file URL */
- oslSecurity pSecurity = osl_getCurrentSecurity();
- osl_getHomeDir( pSecurity , &pTmp2 );
- osl_freeSecurityHandle( pSecurity );
-
- /* 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 );
+ // Handle empty path:
+ if (i == url.getLength()) {
+ *path = "/";
+ return osl_File_E_None;
+ }
+ // Path must not contain %2F:
+ if (url.indexOf("%2F", i) != -1 || url.indexOf("%2f", i) != -1) {
+ return osl_File_E_INVAL;
+ }
+ *path = rtl::Uri::decode(
+ url.copy(i), rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ // Path must not contain %2F:
+ if (path->indexOf('\0') != -1) {
+ return osl_File_E_INVAL;
+ }
+ // Handle ~ notation:
+ if (resolveHome && path->getLength() >= 2 && (*path)[1] == '~') {
+ sal_Int32 j = path->indexOf('/', 2);
+ if (j == -1) {
+ j = path->getLength();
}
-
- else
- {
- /* FIXME: replace ~user with users home directory */
+ if (j == 2) {
+ OUString home;
+ if (!osl::Security().getHomeDir(home)) {
+ SAL_WARN("sal.osl", "osl::Security::getHomeDir failed");
+ return osl_File_E_INVAL;
+ }
+ i = url.indexOf('/', i + 1);
+ if (i == -1) {
+ i = url.getLength();
+ } else {
+ ++i;
+ }
+ //TODO: cheesy way of ensuring home's path ends in slash:
+ if (!home.isEmpty() && home[home.getLength() - 1] != '/') {
+ home += "/";
+ }
+ try {
+ home = rtl::Uri::convertRelToAbs(home, url.copy(i));
+ } catch (rtl::MalformedUriException & e) {
+ SAL_WARN(
+ "sal.osl", "rtl::MalformedUriException " << e.getMessage());
+ return osl_File_E_INVAL;
+ }
+ return getSystemPathFromFileUrl(home, path, false);
+ } else {
+ // FIXME: replace ~user with user's home directory
return osl_File_E_INVAL;
}
}
-
- rtl_uString_assign ( pustrSystemPath, pTmp );
- rtl_uString_release ( pTmp );
return osl_File_E_None;
}
+}
+
+oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
+{
+ OUString path;
+ auto e = getSystemPathFromFileUrl(
+ OUString::unacquired(&ustrFileURL), &path, true);
+ if (e == osl_File_E_None) {
+ rtl_uString_assign(pustrSystemPath, path.pData);
+ }
+ return e;
+}
+
oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
{
static const sal_Unicode pDoubleSlash[2] = { '/', '/' };