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; }
// Handle authority:
if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) ) if (url.getLength() - i >= 2 && url[i] == '/' && url[i + 1] == '/') {
{ i += 2;
rtl_uString * ustrPathToken = NULL; sal_Int32 j = url.indexOf('/', i);
sal_Int32 nOffset = 7; if (j == -1) {
j = url.getLength();
do }
{ if (j != i
nOffset += nIndex; && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
url.pData->buffer + i, j - i,
/* break url down in '/' divided tokens tokens */ RTL_CONSTASCII_STRINGPARAM("localhost"))
nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, '/' ); != 0)
&& (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
/* copy token to new string */ url.pData->buffer + i, j - i,
rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset, RTL_CONSTASCII_STRINGPARAM("127.0.0.1"))
-1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ ); != 0))
/* 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; return osl_File_E_INVAL;
} }
i = j;
} while( -1 != nIndex );
/* release temporary string and restore index variable */
rtl_uString_release( ustrPathToken );
nIndex = 0;
} }
// Handle empty path:
/* protocol and server should not be encoded, so decode the whole string */ if (i == url.getLength()) {
rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp ); *path = "/";
return osl_File_E_None;
/* 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 );
} }
// Path must not contain %2F:
/* skip "localhost" or "127.0.0.1" if "file://" is specified */ if (url.indexOf("%2F", i) != -1 || url.indexOf("%2f", i) != -1) {
/* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */ return osl_File_E_INVAL;
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 ) ) )
{
/* don't exclude the '/' */
nIndex += 9;
} }
*path = rtl::Uri::decode(
rtl_uString_release( pServer ); 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( nIndex ) if (resolveHome && path->getLength() >= 2 && (*path)[1] == '~') {
rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex ); sal_Int32 j = path->indexOf('/', 2);
if (j == -1) {
/* check if system path starts with ~ or ~user and replace it with the appropriate home dir */ j = path->getLength();
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 );
} }
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