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 @@
#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] = { '/', '/' };
......
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