Kaydet (Commit) 62dbe2e6 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Clean up osl_getSystemPathFromFileURL implementation

Change-Id: I2daa355c4a46c4edc73c30185f2b31852351c45f
üst c5fefe46
...@@ -21,22 +21,25 @@ ...@@ -21,22 +21,25 @@
#include "system.hxx" #include "system.hxx"
#include <cassert>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
#include "osl/file.hxx" #include "osl/file.hxx"
#include <osl/security.h> #include <osl/security.hxx>
#include <osl/diagnose.h> #include <osl/diagnose.h>
#include <osl/thread.h> #include <osl/thread.h>
#include <osl/process.h> #include <osl/process.h>
#include <rtl/character.hxx> #include <rtl/character.hxx>
#include <rtl/uri.h> #include <rtl/uri.h>
#include <rtl/uri.hxx>
#include <rtl/ustring.hxx> #include <rtl/ustring.hxx>
#include <rtl/ustrbuf.h> #include <rtl/ustrbuf.h>
#include "rtl/textcvt.h" #include "rtl/textcvt.h"
#include <sal/log.hxx>
#include "file_error_transl.hxx" #include "file_error_transl.hxx"
#include "file_path_helper.hxx" #include "file_path_helper.hxx"
...@@ -81,36 +84,35 @@ oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uStrin ...@@ -81,36 +84,35 @@ oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uStrin
return osl_File_E_None; return osl_File_E_None;
} }
oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath ) namespace {
{
sal_Int32 nIndex;
rtl_uString * pTmp = NULL;
sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
oslFileError getSystemPathFromFileUrl(
OUString const & url, OUString * path, bool resolveHome)
{
assert(path != nullptr);
// For compatibility with assumptions in other parts of the code base, // 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 // 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 // (relative) file URL (except if it starts with two slashes, in which case
// it is a relative URL with an authority component): // it is a relative URL with an authority component):
if (ustrFileURL->length == 0 if (url.isEmpty()
|| (ustrFileURL->buffer[0] == '/' || (url[0] == '/' && (url.getLength() == 1 || url[1] != '/')))
&& (ustrFileURL->length == 1 || ustrFileURL->buffer[1] != '/')))
{ {
return osl_File_E_INVAL; return osl_File_E_INVAL;
} }
// Check for non file scheme: // Check for non file scheme:
if (rtl::isAsciiAlpha(ustrFileURL->buffer[0])) { sal_Int32 i = 0;
for (sal_Int32 i = 1; i != ustrFileURL->length; ++i) { if (rtl::isAsciiAlpha(url[0])) {
auto c = ustrFileURL->buffer[i]; for (sal_Int32 j = 1; j != url.getLength(); ++j) {
auto c = url[j];
if (c == ':') { if (c == ':') {
if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths( if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
ustrFileURL->buffer, i, url.pData->buffer, j,
RTL_CONSTASCII_STRINGPARAM("file")) RTL_CONSTASCII_STRINGPARAM("file"))
!= 0) != 0)
{ {
return osl_File_E_INVAL; return osl_File_E_INVAL;
} }
i = j + 1;
break; break;
} else if (!rtl::isAsciiAlphanumeric(c) && c != '+' && c != '-' } else if (!rtl::isAsciiAlphanumeric(c) && c != '+' && c != '-'
&& c != '.') && c != '.')
...@@ -119,121 +121,97 @@ oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rt ...@@ -119,121 +121,97 @@ oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rt
} }
} }
} }
// Handle query or fragment:
/* search for encoded slashes (%2F) and decode every single token if we find one */ if (url.indexOf('?', i) != -1 || url.indexOf('#', i) != -1) {
return osl_File_E_INVAL;
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 authority:
/* skip "localhost" or "127.0.0.1" if "file://" is specified */ if (url.getLength() - i >= 2 && url[i] == '/' && url[i + 1] == '/') {
/* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ i += 2;
if( nIndex && ( 10 <= pTmp->length - nIndex ) ) sal_Int32 j = url.indexOf('/', i);
{ if (j == -1) {
rtl_uString * pServer = NULL; j = url.getLength();
rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 ); }
if (j != i
/* server is case insensitive */ && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length ); url.pData->buffer + i, j - i,
RTL_CONSTASCII_STRINGPARAM("localhost"))
if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) || != 0)
( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) ) && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
url.pData->buffer + i, j - i,
RTL_CONSTASCII_STRINGPARAM("127.0.0.1"))
!= 0))
{ {
/* don't exclude the '/' */ return osl_File_E_INVAL;
nIndex += 9;
} }
i = j;
rtl_uString_release( pServer );
} }
// Handle empty path:
if( nIndex ) if (i == url.getLength()) {
rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex ); *path = "/";
return osl_File_E_None;
/* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ }
if( '~' == pTmp->buffer[0] ) // Path must not contain %2F:
{ if (url.indexOf("%2F", i) != -1 || url.indexOf("%2f", i) != -1) {
/* check if another user is specified */ return osl_File_E_INVAL;
if( ( 1 == pTmp->length ) || ( '/' == pTmp->buffer[1] ) ) }
{ *path = rtl::Uri::decode(
rtl_uString *pTmp2 = NULL; url.copy(i), rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
// Path must not contain %2F:
/* osl_getHomeDir returns file URL */ if (path->indexOf('\0') != -1) {
oslSecurity pSecurity = osl_getCurrentSecurity(); return osl_File_E_INVAL;
osl_getHomeDir( pSecurity , &pTmp2 ); }
osl_freeSecurityHandle( pSecurity ); // Handle ~ notation:
if (resolveHome && path->getLength() >= 2 && (*path)[1] == '~') {
/* remove "file://" prefix */ sal_Int32 j = path->indexOf('/', 2);
rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 ); if (j == -1) {
j = path->getLength();
/* replace '~' in original string */
rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
rtl_uString_release( pTmp2 );
} }
if (j == 2) {
else OUString home;
{ if (!osl::Security().getHomeDir(home)) {
/* FIXME: replace ~user with users home directory */ 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; return osl_File_E_INVAL;
} }
} }
rtl_uString_assign ( pustrSystemPath, pTmp );
rtl_uString_release ( pTmp );
return osl_File_E_None; 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 ) oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
{ {
static const sal_Unicode pDoubleSlash[2] = { '/', '/' }; static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment