[Libreoffice-commits] core.git: sal/osl

Stephan Bergmann sbergman at redhat.com
Tue Nov 3 23:07:16 PST 2015


 sal/osl/unx/file_url.cxx |  216 +++++++++++++++++++++--------------------------
 1 file changed, 97 insertions(+), 119 deletions(-)

New commits:
commit 62dbe2e6eb30660f252b4e2c048f4aecf28e41c6
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Wed Nov 4 08:01:13 2015 +0100

    Clean up osl_getSystemPathFromFileURL implementation
    
    Change-Id: I2daa355c4a46c4edc73c30185f2b31852351c45f

diff --git a/sal/osl/unx/file_url.cxx b/sal/osl/unx/file_url.cxx
index 1d8c1fd..c0cbe5b 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] = { '/', '/' };


More information about the Libreoffice-commits mailing list