xref: /trunk/main/sal/osl/unx/file_url.cxx (revision 0170220d0d03207a9b1c8adedf497cb639fcddf8)
187d2adbcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
387d2adbcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
487d2adbcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
587d2adbcSAndrew Rist  * distributed with this work for additional information
687d2adbcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
787d2adbcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
887d2adbcSAndrew Rist  * "License"); you may not use this file except in compliance
987d2adbcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
1187d2adbcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
1387d2adbcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1487d2adbcSAndrew Rist  * software distributed under the License is distributed on an
1587d2adbcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1687d2adbcSAndrew Rist  * KIND, either express or implied.  See the License for the
1787d2adbcSAndrew Rist  * specific language governing permissions and limitations
1887d2adbcSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
2087d2adbcSAndrew Rist  *************************************************************/
2187d2adbcSAndrew Rist 
2287d2adbcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sal.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "file_url.h"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "system.h"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <limits.h>
32cdf0e10cSrcweir #include <errno.h>
33cdf0e10cSrcweir #include <strings.h>
34cdf0e10cSrcweir #include <unistd.h>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include "osl/file.hxx"
37cdf0e10cSrcweir #include <osl/security.h>
38cdf0e10cSrcweir #include <osl/diagnose.h>
39cdf0e10cSrcweir #include <osl/thread.h>
40cdf0e10cSrcweir #include <osl/process.h>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include <rtl/uri.h>
43cdf0e10cSrcweir #include <rtl/ustring.hxx>
44cdf0e10cSrcweir #include <rtl/ustrbuf.h>
45cdf0e10cSrcweir #include "rtl/textcvt.h"
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #include "file_error_transl.h"
48cdf0e10cSrcweir #include "file_path_helper.hxx"
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include "uunxapi.hxx"
51cdf0e10cSrcweir 
52cdf0e10cSrcweir /***************************************************
53cdf0e10cSrcweir 
54cdf0e10cSrcweir  General note
55cdf0e10cSrcweir 
56cdf0e10cSrcweir  This file contains the part that handles File URLs.
57cdf0e10cSrcweir 
58cdf0e10cSrcweir  File URLs as scheme specific notion of URIs
59*0170220dSmseidel  (RFC2396) may be handled platform independent, but
60cdf0e10cSrcweir  will not in osl which is considered wrong.
61cdf0e10cSrcweir  Future version of osl should handle File URLs this
62cdf0e10cSrcweir  way. In rtl/uri there is already an URI parser etc.
63cdf0e10cSrcweir  so this code should be consolidated.
64cdf0e10cSrcweir 
65cdf0e10cSrcweir  **************************************************/
66cdf0e10cSrcweir /************************************************************************
67cdf0e10cSrcweir  * ToDo
68cdf0e10cSrcweir  *
69cdf0e10cSrcweir  * Fix osl_getCanonicalName
70cdf0e10cSrcweir  ***********************************************************************/
71cdf0e10cSrcweir 
72cdf0e10cSrcweir 
73cdf0e10cSrcweir /***************************************************
74cdf0e10cSrcweir  * namespace directives
75cdf0e10cSrcweir  **************************************************/
76cdf0e10cSrcweir 
77cdf0e10cSrcweir using namespace osl;
78cdf0e10cSrcweir 
79cdf0e10cSrcweir /***************************************************
80cdf0e10cSrcweir  * constants
81cdf0e10cSrcweir  **************************************************/
82cdf0e10cSrcweir 
83cdf0e10cSrcweir const sal_Unicode UNICHAR_SLASH = ((sal_Unicode)'/');
84cdf0e10cSrcweir const sal_Unicode UNICHAR_COLON = ((sal_Unicode)':');
85cdf0e10cSrcweir const sal_Unicode UNICHAR_DOT   = ((sal_Unicode)'.');
86cdf0e10cSrcweir 
87cdf0e10cSrcweir /******************************************************************************
88cdf0e10cSrcweir  * Exported Module Functions
89cdf0e10cSrcweir  *****************************************************************************/
90cdf0e10cSrcweir 
91cdf0e10cSrcweir /* a slightly modified version of Pchar in rtl/source/uri.c */
92cdf0e10cSrcweir const sal_Bool uriCharClass[128] =
93cdf0e10cSrcweir {
94cdf0e10cSrcweir   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
95cdf0e10cSrcweir   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96cdf0e10cSrcweir   0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./  */
97cdf0e10cSrcweir   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
98cdf0e10cSrcweir   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
99cdf0e10cSrcweir   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
100cdf0e10cSrcweir   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
101cdf0e10cSrcweir   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0  /* pqrstuvwxyz{|}~  */
102cdf0e10cSrcweir };
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 
105cdf0e10cSrcweir /* check for top wrong usage strings */
106cdf0e10cSrcweir /*
107cdf0e10cSrcweir static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir     rtl_uString *pTmp = NULL;
110cdf0e10cSrcweir     sal_Bool bRet;
111cdf0e10cSrcweir 
112cdf0e10cSrcweir     rtl_uString_newFromStr_WithLength( &pTmp, path, len );
113cdf0e10cSrcweir 
114cdf0e10cSrcweir     rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
115cdf0e10cSrcweir 
116cdf0e10cSrcweir     bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
117cdf0e10cSrcweir            ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
118cdf0e10cSrcweir            ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
119cdf0e10cSrcweir            ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
120cdf0e10cSrcweir            ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     rtl_uString_release( pTmp );
123cdf0e10cSrcweir     return bRet;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir */
126cdf0e10cSrcweir 
127cdf0e10cSrcweir /****************************************************************************/
128cdf0e10cSrcweir /* osl_getCanonicalName */
129cdf0e10cSrcweir /****************************************************************************/
130cdf0e10cSrcweir 
osl_getCanonicalName(rtl_uString * ustrFileURL,rtl_uString ** pustrValidURL)131cdf0e10cSrcweir oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
132cdf0e10cSrcweir {
133cdf0e10cSrcweir     OSL_ENSURE(0, "osl_getCanonicalName not implemented");
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     rtl_uString_newFromString(pustrValidURL, ustrFileURL);
136cdf0e10cSrcweir     return osl_File_E_None;
137cdf0e10cSrcweir }
138cdf0e10cSrcweir 
139cdf0e10cSrcweir /****************************************************************************/
140cdf0e10cSrcweir /* osl_getSystemPathFromFileURL */
141cdf0e10cSrcweir /****************************************************************************/
142cdf0e10cSrcweir 
osl_getSystemPathFromFileURL(rtl_uString * ustrFileURL,rtl_uString ** pustrSystemPath)143cdf0e10cSrcweir oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
144cdf0e10cSrcweir {
145cdf0e10cSrcweir     sal_Int32 nIndex;
146cdf0e10cSrcweir     rtl_uString * pTmp = NULL;
147cdf0e10cSrcweir 
148cdf0e10cSrcweir     sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
149cdf0e10cSrcweir     sal_Unicode protocolDelimiter[3] = { ':', '/', '/' };
150cdf0e10cSrcweir 
151cdf0e10cSrcweir     /* temporary hack: if already system path, return ustrFileURL */
152cdf0e10cSrcweir     /*
153cdf0e10cSrcweir     if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
154cdf0e10cSrcweir     {
155cdf0e10cSrcweir         OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
156cdf0e10cSrcweir         rtl_uString_assign( pustrSystemPath, ustrFileURL );
157cdf0e10cSrcweir         return osl_File_E_None;
158cdf0e10cSrcweir     }
159cdf0e10cSrcweir     */
160cdf0e10cSrcweir 
161cdf0e10cSrcweir     /* a valid file url may not start with '/' */
162cdf0e10cSrcweir     if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) )
163cdf0e10cSrcweir     {
164cdf0e10cSrcweir         return osl_File_E_INVAL;
165cdf0e10cSrcweir     }
166cdf0e10cSrcweir 
167cdf0e10cSrcweir     /* Check for non file:// protocols */
168cdf0e10cSrcweir 
169cdf0e10cSrcweir     nIndex = rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, protocolDelimiter, 3 );
170cdf0e10cSrcweir     if ( -1 != nIndex && (4 != nIndex || 0 != rtl_ustr_ascii_shortenedCompare_WithLength( ustrFileURL->buffer, ustrFileURL->length,"file", 4 ) ) )
171cdf0e10cSrcweir     {
172cdf0e10cSrcweir         return osl_File_E_INVAL;
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     /* search for encoded slashes (%2F) and decode every single token if we find one */
176cdf0e10cSrcweir 
177cdf0e10cSrcweir     nIndex = 0;
178cdf0e10cSrcweir 
179cdf0e10cSrcweir     if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) )
180cdf0e10cSrcweir     {
181cdf0e10cSrcweir         rtl_uString * ustrPathToken = NULL;
182cdf0e10cSrcweir         sal_Int32 nOffset = 7;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir         do
185cdf0e10cSrcweir         {
186cdf0e10cSrcweir             nOffset += nIndex;
187cdf0e10cSrcweir 
18886e1cf34SPedro Giffuni             /* break url down in '/' divided tokens tokens */
189cdf0e10cSrcweir             nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' );
190cdf0e10cSrcweir 
191cdf0e10cSrcweir             /* copy token to new string */
192cdf0e10cSrcweir             rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset,
193cdf0e10cSrcweir                 -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ );
194cdf0e10cSrcweir 
195cdf0e10cSrcweir             /* decode token */
196cdf0e10cSrcweir             rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
197cdf0e10cSrcweir 
198cdf0e10cSrcweir             /* the result should not contain any '/' */
199cdf0e10cSrcweir             if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) )
200cdf0e10cSrcweir             {
201cdf0e10cSrcweir                 rtl_uString_release( pTmp );
202cdf0e10cSrcweir                 rtl_uString_release( ustrPathToken );
203cdf0e10cSrcweir 
204cdf0e10cSrcweir                 return osl_File_E_INVAL;
205cdf0e10cSrcweir             }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir         } while( -1 != nIndex );
208cdf0e10cSrcweir 
209cdf0e10cSrcweir         /* release temporary string and restore index variable */
210cdf0e10cSrcweir         rtl_uString_release( ustrPathToken );
211cdf0e10cSrcweir         nIndex = 0;
212cdf0e10cSrcweir     }
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     /* protocol and server should not be encoded, so decode the whole string */
215cdf0e10cSrcweir     rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
216cdf0e10cSrcweir 
217cdf0e10cSrcweir     /* check if file protocol specified */
218cdf0e10cSrcweir     /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
219cdf0e10cSrcweir     if( 7 <= pTmp->length )
220cdf0e10cSrcweir     {
221cdf0e10cSrcweir         rtl_uString * pProtocol = NULL;
222cdf0e10cSrcweir         rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 );
223cdf0e10cSrcweir 
224cdf0e10cSrcweir         /* protocol is case insensitive */
225cdf0e10cSrcweir         rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length );
226cdf0e10cSrcweir 
227cdf0e10cSrcweir         if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) )
228cdf0e10cSrcweir             nIndex = 7;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         rtl_uString_release( pProtocol );
231cdf0e10cSrcweir     }
232cdf0e10cSrcweir 
233cdf0e10cSrcweir     /* skip "localhost" or "127.0.0.1" if "file://" is specified */
234cdf0e10cSrcweir     /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
235cdf0e10cSrcweir     if( nIndex && ( 10 <= pTmp->length - nIndex ) )
236cdf0e10cSrcweir     {
237cdf0e10cSrcweir         rtl_uString * pServer = NULL;
238cdf0e10cSrcweir         rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 );
239cdf0e10cSrcweir 
240cdf0e10cSrcweir         /* server is case insensitive */
241cdf0e10cSrcweir         rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir         if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) ||
244cdf0e10cSrcweir             ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) )
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             /* don't exclude the '/' */
247cdf0e10cSrcweir             nIndex += 9;
248cdf0e10cSrcweir         }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir         rtl_uString_release( pServer );
251cdf0e10cSrcweir     }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir     if( nIndex )
254cdf0e10cSrcweir         rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex );
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
257cdf0e10cSrcweir     if( (sal_Unicode) '~' == pTmp->buffer[0] )
258cdf0e10cSrcweir     {
259cdf0e10cSrcweir         /* check if another user is specified */
260cdf0e10cSrcweir         if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) )
261cdf0e10cSrcweir         {
262cdf0e10cSrcweir             rtl_uString *pTmp2 = NULL;
2639717b33aSPedro Giffuni             oslSecurity pSecTemp;
264cdf0e10cSrcweir 
265cdf0e10cSrcweir             /* osl_getHomeDir returns file URL */
2669717b33aSPedro Giffuni             osl_getHomeDir( pSecTemp = osl_getCurrentSecurity(), &pTmp2 );
2679717b33aSPedro Giffuni             osl_freeSecurityHandle( pSecTemp );
268cdf0e10cSrcweir 
269cdf0e10cSrcweir             /* remove "file://" prefix */
270cdf0e10cSrcweir             rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 );
271cdf0e10cSrcweir 
272cdf0e10cSrcweir             /* replace '~' in original string */
273cdf0e10cSrcweir             rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
274cdf0e10cSrcweir             rtl_uString_release( pTmp2 );
275cdf0e10cSrcweir         }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir         else
278cdf0e10cSrcweir         {
279cdf0e10cSrcweir             /* FIXME: replace ~user with users home directory */
280cdf0e10cSrcweir             return osl_File_E_INVAL;
281cdf0e10cSrcweir         }
282cdf0e10cSrcweir     }
283cdf0e10cSrcweir 
284*0170220dSmseidel     /* temporary check for top 5 wrong usage strings (which are valid but unlikely filenames) */
285cdf0e10cSrcweir     /*
286cdf0e10cSrcweir     OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
287cdf0e10cSrcweir     */
288cdf0e10cSrcweir 
289cdf0e10cSrcweir     *pustrSystemPath = pTmp;
290cdf0e10cSrcweir     return osl_File_E_None;
291cdf0e10cSrcweir }
292cdf0e10cSrcweir 
293cdf0e10cSrcweir /****************************************************************************/
294cdf0e10cSrcweir /* osl_getFileURLFromSystemPath */
295cdf0e10cSrcweir /****************************************************************************/
296cdf0e10cSrcweir 
osl_getFileURLFromSystemPath(rtl_uString * ustrSystemPath,rtl_uString ** pustrFileURL)297cdf0e10cSrcweir oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
298cdf0e10cSrcweir {
299cdf0e10cSrcweir     static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
300cdf0e10cSrcweir 
301cdf0e10cSrcweir     rtl_uString *pTmp = NULL;
302cdf0e10cSrcweir     sal_Int32 nIndex;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir     if( 0 == ustrSystemPath->length )
305cdf0e10cSrcweir         return osl_File_E_INVAL;
306cdf0e10cSrcweir 
307cdf0e10cSrcweir     /* temporary hack: if already file url, return ustrSystemPath */
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) )
310cdf0e10cSrcweir     {
311cdf0e10cSrcweir     /*
312cdf0e10cSrcweir         if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
313cdf0e10cSrcweir         {
314cdf0e10cSrcweir             OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
315cdf0e10cSrcweir             rtl_uString_assign( pustrFileURL, ustrSystemPath );
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir         else
318cdf0e10cSrcweir         {
319cdf0e10cSrcweir             rtl_uString *pTmp2 = NULL;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir             OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
322cdf0e10cSrcweir             rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
323cdf0e10cSrcweir             rtl_uString_newFromAscii( &pTmp2, "file://" );
324cdf0e10cSrcweir             rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
325cdf0e10cSrcweir             rtl_uString_release( pTmp2 );
326cdf0e10cSrcweir         }
327cdf0e10cSrcweir         return osl_File_E_None;
328cdf0e10cSrcweir         */
329cdf0e10cSrcweir         return osl_File_E_INVAL;
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 
333cdf0e10cSrcweir     /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
334cdf0e10cSrcweir     if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] )
335cdf0e10cSrcweir     {
336cdf0e10cSrcweir         /* check if another user is specified */
337cdf0e10cSrcweir         if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) )
338cdf0e10cSrcweir         {
339cdf0e10cSrcweir             /* osl_getHomeDir returns file URL */
340cdf0e10cSrcweir             osl_getHomeDir( osl_getCurrentSecurity(), &pTmp );
341cdf0e10cSrcweir 
342cdf0e10cSrcweir             /* remove "file://" prefix */
343cdf0e10cSrcweir             rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
344cdf0e10cSrcweir 
345cdf0e10cSrcweir             /* replace '~' in original string */
346cdf0e10cSrcweir             rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
347cdf0e10cSrcweir         }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir         else
350cdf0e10cSrcweir         {
351cdf0e10cSrcweir             /* FIXME: replace ~user with users home directory */
352cdf0e10cSrcweir             return osl_File_E_INVAL;
353cdf0e10cSrcweir         }
354cdf0e10cSrcweir     }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir     /* check if initial string contains double instances of '/' */
357cdf0e10cSrcweir     nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
358cdf0e10cSrcweir     if( -1 != nIndex )
359cdf0e10cSrcweir     {
360cdf0e10cSrcweir         sal_Int32 nSrcIndex;
361cdf0e10cSrcweir         sal_Int32 nDeleted = 0;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir         /* if pTmp is not already allocated, copy ustrSystemPath for modification */
364cdf0e10cSrcweir         if( NULL == pTmp )
365cdf0e10cSrcweir             rtl_uString_newFromString( &pTmp, ustrSystemPath );
366cdf0e10cSrcweir 
367cdf0e10cSrcweir         /* adapt index to pTmp */
368cdf0e10cSrcweir         nIndex += pTmp->length - ustrSystemPath->length;
369cdf0e10cSrcweir 
37086e1cf34SPedro Giffuni         /* remove all occurrences of '//' */
371cdf0e10cSrcweir         for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
372cdf0e10cSrcweir         {
373cdf0e10cSrcweir             if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) )
374cdf0e10cSrcweir                 nDeleted++;
375cdf0e10cSrcweir             else
376cdf0e10cSrcweir                 pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
377cdf0e10cSrcweir         }
378cdf0e10cSrcweir 
379cdf0e10cSrcweir         /* adjust length member */
380cdf0e10cSrcweir         pTmp->length -= nDeleted;
381cdf0e10cSrcweir     }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     if( NULL == pTmp )
384cdf0e10cSrcweir         rtl_uString_assign( &pTmp, ustrSystemPath );
385cdf0e10cSrcweir 
386*0170220dSmseidel     /* temporary check for top 5 wrong usage strings (which are valid but unlikely filenames) */
387cdf0e10cSrcweir     /*
388cdf0e10cSrcweir     OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
389cdf0e10cSrcweir     */
390cdf0e10cSrcweir 
391cdf0e10cSrcweir     /* file URLs must be URI encoded */
392cdf0e10cSrcweir     rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
393cdf0e10cSrcweir 
394cdf0e10cSrcweir     rtl_uString_release( pTmp );
395cdf0e10cSrcweir 
396cdf0e10cSrcweir     /* absolute urls should start with 'file://' */
397cdf0e10cSrcweir     if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] )
398cdf0e10cSrcweir     {
399cdf0e10cSrcweir         rtl_uString *pProtocol = NULL;
400cdf0e10cSrcweir 
401cdf0e10cSrcweir         rtl_uString_newFromAscii( &pProtocol, "file://" );
402cdf0e10cSrcweir         rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
403cdf0e10cSrcweir         rtl_uString_release( pProtocol );
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     return osl_File_E_None;
407cdf0e10cSrcweir }
408cdf0e10cSrcweir 
409cdf0e10cSrcweir /****************************************************************************
410cdf0e10cSrcweir  * osl_getSystemPathFromFileURL_Ex - helper function
411cdf0e10cSrcweir  * clients may specify if they want to accept relative
412cdf0e10cSrcweir  * URLs or not
413cdf0e10cSrcweir  ****************************************************************************/
414cdf0e10cSrcweir 
osl_getSystemPathFromFileURL_Ex(rtl_uString * ustrFileURL,rtl_uString ** pustrSystemPath,sal_Bool bAllowRelative)415cdf0e10cSrcweir oslFileError osl_getSystemPathFromFileURL_Ex(
416cdf0e10cSrcweir     rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
417cdf0e10cSrcweir {
418cdf0e10cSrcweir     rtl_uString* temp = 0;
419cdf0e10cSrcweir     oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
420cdf0e10cSrcweir 
421cdf0e10cSrcweir     if (osl_File_E_None == osl_error)
422cdf0e10cSrcweir     {
423cdf0e10cSrcweir         if (bAllowRelative || (UNICHAR_SLASH == temp->buffer[0]))
424cdf0e10cSrcweir         {
425cdf0e10cSrcweir             *pustrSystemPath = temp;
426cdf0e10cSrcweir         }
427cdf0e10cSrcweir         else
428cdf0e10cSrcweir         {
429cdf0e10cSrcweir             rtl_uString_release(temp);
430cdf0e10cSrcweir             osl_error = osl_File_E_INVAL;
431cdf0e10cSrcweir         }
432cdf0e10cSrcweir     }
433cdf0e10cSrcweir 
434cdf0e10cSrcweir     return osl_error;
435cdf0e10cSrcweir }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir namespace /* private */
438cdf0e10cSrcweir {
439cdf0e10cSrcweir 
440cdf0e10cSrcweir     /******************************************************
441cdf0e10cSrcweir      * Helper function, return a pinter to the final '\0'
442cdf0e10cSrcweir      * of a string
443cdf0e10cSrcweir      ******************************************************/
444cdf0e10cSrcweir 
ustrtoend(sal_Unicode * pStr)445cdf0e10cSrcweir     sal_Unicode* ustrtoend(sal_Unicode* pStr)
446cdf0e10cSrcweir     {
447cdf0e10cSrcweir         return (pStr + rtl_ustr_getLength(pStr));
448cdf0e10cSrcweir     }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     /*********************************************
451cdf0e10cSrcweir 
452cdf0e10cSrcweir      ********************************************/
453cdf0e10cSrcweir 
ustrchrcat(const sal_Unicode chr,sal_Unicode * d)454cdf0e10cSrcweir     sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
455cdf0e10cSrcweir     {
456cdf0e10cSrcweir         sal_Unicode* p = ustrtoend(d);
457cdf0e10cSrcweir         *p++ = chr;
458cdf0e10cSrcweir         *p   = 0;
459cdf0e10cSrcweir         return d;
460cdf0e10cSrcweir     }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir     /******************************************************
463cdf0e10cSrcweir      *
464cdf0e10cSrcweir      ******************************************************/
465cdf0e10cSrcweir 
_islastchr(sal_Unicode * pStr,sal_Unicode Chr)466cdf0e10cSrcweir     bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
467cdf0e10cSrcweir     {
468cdf0e10cSrcweir         sal_Unicode* p = ustrtoend(pStr);
469cdf0e10cSrcweir         if (p > pStr)
470cdf0e10cSrcweir             p--;
471cdf0e10cSrcweir         return (*p == Chr);
472cdf0e10cSrcweir     }
473cdf0e10cSrcweir 
474cdf0e10cSrcweir     /******************************************************
475cdf0e10cSrcweir      * Remove the last part of a path, a path that has
476cdf0e10cSrcweir      * only a '/' or no '/' at all will be returned
477cdf0e10cSrcweir      * unmodified
478cdf0e10cSrcweir      ******************************************************/
479cdf0e10cSrcweir 
_rmlastpathtoken(sal_Unicode * aPath)480cdf0e10cSrcweir     sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
481cdf0e10cSrcweir     {
482cdf0e10cSrcweir         /*  we always may skip -2 because we
483cdf0e10cSrcweir             may at least stand on a '/' but
484cdf0e10cSrcweir             either there is no other character
485cdf0e10cSrcweir             before this '/' or it's another
486cdf0e10cSrcweir             character than the '/'
487cdf0e10cSrcweir         */
488cdf0e10cSrcweir         sal_Unicode* p = ustrtoend(aPath) - 2;
489cdf0e10cSrcweir 
490cdf0e10cSrcweir         // move back to the next path separator
491cdf0e10cSrcweir         // or to the start of the string
492cdf0e10cSrcweir         while ((p > aPath) && (*p != UNICHAR_SLASH))
493cdf0e10cSrcweir             p--;
494cdf0e10cSrcweir 
495cdf0e10cSrcweir         if (p >= aPath)
496cdf0e10cSrcweir         {
497cdf0e10cSrcweir             if (UNICHAR_SLASH == *p)
498cdf0e10cSrcweir             {
499cdf0e10cSrcweir                 p++;
500cdf0e10cSrcweir                *p = '\0';
501cdf0e10cSrcweir             }
502cdf0e10cSrcweir             else
503cdf0e10cSrcweir             {
504cdf0e10cSrcweir                *p = '\0';
505cdf0e10cSrcweir             }
506cdf0e10cSrcweir         }
507cdf0e10cSrcweir 
508cdf0e10cSrcweir         return aPath;
509cdf0e10cSrcweir     }
510cdf0e10cSrcweir 
511cdf0e10cSrcweir     /******************************************************
512cdf0e10cSrcweir      *
513cdf0e10cSrcweir      ******************************************************/
514cdf0e10cSrcweir 
_osl_resolvepath(sal_Unicode * path,sal_Unicode * current_pos,bool * failed)515cdf0e10cSrcweir     oslFileError _osl_resolvepath(
516cdf0e10cSrcweir         /*inout*/ sal_Unicode* path,
517cdf0e10cSrcweir         /*inout*/ sal_Unicode* current_pos,
518cdf0e10cSrcweir         /*inout*/ bool* failed)
519cdf0e10cSrcweir     {
520cdf0e10cSrcweir         oslFileError ferr = osl_File_E_None;
521cdf0e10cSrcweir 
522cdf0e10cSrcweir         if (!*failed)
523cdf0e10cSrcweir         {
524cdf0e10cSrcweir             char unresolved_path[PATH_MAX];
525cdf0e10cSrcweir             if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
526cdf0e10cSrcweir                 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
527cdf0e10cSrcweir 
528cdf0e10cSrcweir             char resolved_path[PATH_MAX];
529cdf0e10cSrcweir             if (realpath(unresolved_path, resolved_path))
530cdf0e10cSrcweir             {
531cdf0e10cSrcweir                 if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
532cdf0e10cSrcweir                     return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
533cdf0e10cSrcweir 
534cdf0e10cSrcweir                 current_pos = ustrtoend(path) - 1;
535cdf0e10cSrcweir             }
536cdf0e10cSrcweir             else
537cdf0e10cSrcweir             {
538cdf0e10cSrcweir                 if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
539cdf0e10cSrcweir                     *failed = true;
540cdf0e10cSrcweir                 else
541cdf0e10cSrcweir                     ferr = oslTranslateFileError(OSL_FET_ERROR, errno);
542cdf0e10cSrcweir             }
543cdf0e10cSrcweir         }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir         return ferr;
546cdf0e10cSrcweir     }
547cdf0e10cSrcweir 
548cdf0e10cSrcweir     /******************************************************
549cdf0e10cSrcweir      * Works even with non existing paths. The resulting
550cdf0e10cSrcweir      * path must not exceed PATH_MAX else
551cdf0e10cSrcweir      * osl_File_E_NAMETOOLONG is the result
552cdf0e10cSrcweir      ******************************************************/
553cdf0e10cSrcweir 
osl_getAbsoluteFileURL_impl_(const rtl::OUString & unresolved_path,rtl::OUString & resolved_path)554cdf0e10cSrcweir     oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path)
555cdf0e10cSrcweir     {
556cdf0e10cSrcweir         // the given unresolved path must not exceed PATH_MAX
557cdf0e10cSrcweir         if (unresolved_path.getLength() >= (PATH_MAX - 2))
558cdf0e10cSrcweir             return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
559cdf0e10cSrcweir 
560cdf0e10cSrcweir         sal_Unicode        path_resolved_so_far[PATH_MAX];
561cdf0e10cSrcweir         const sal_Unicode* punresolved = unresolved_path.getStr();
562cdf0e10cSrcweir         sal_Unicode*       presolvedsf = path_resolved_so_far;
563cdf0e10cSrcweir 
564cdf0e10cSrcweir         // reserve space for leading '/' and trailing '\0'
565cdf0e10cSrcweir         // do not exceed this limit
566cdf0e10cSrcweir         sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
567cdf0e10cSrcweir 
568cdf0e10cSrcweir         // if realpath fails with error ENOTDIR, EACCES or ENOENT
569cdf0e10cSrcweir         // we will not call it again, because _osl_realpath should also
570cdf0e10cSrcweir         // work with non existing directories etc.
571cdf0e10cSrcweir         bool realpath_failed = false;
572cdf0e10cSrcweir         oslFileError ferr;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir         path_resolved_so_far[0] = '\0';
575cdf0e10cSrcweir 
576cdf0e10cSrcweir         while (*punresolved != '\0')
577cdf0e10cSrcweir         {
578cdf0e10cSrcweir             // ignore '/.' , skip one part back when '/..'
579cdf0e10cSrcweir 
580cdf0e10cSrcweir             if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf))
581cdf0e10cSrcweir             {
582cdf0e10cSrcweir                 if ('\0' == *(punresolved + 1))
583cdf0e10cSrcweir                 {
584cdf0e10cSrcweir                     punresolved++;
585cdf0e10cSrcweir                     continue;
586cdf0e10cSrcweir                 }
587cdf0e10cSrcweir                 else if (UNICHAR_SLASH == *(punresolved + 1))
588cdf0e10cSrcweir                 {
589cdf0e10cSrcweir                     punresolved += 2;
590cdf0e10cSrcweir                     continue;
591cdf0e10cSrcweir                 }
592cdf0e10cSrcweir                 else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2))))
593cdf0e10cSrcweir                 {
594cdf0e10cSrcweir                     _rmlastpathtoken(path_resolved_so_far);
595cdf0e10cSrcweir 
596cdf0e10cSrcweir                     presolvedsf = ustrtoend(path_resolved_so_far) - 1;
597cdf0e10cSrcweir 
598cdf0e10cSrcweir                     if (UNICHAR_SLASH == *(punresolved + 2))
599cdf0e10cSrcweir                         punresolved += 3;
600cdf0e10cSrcweir                     else
601cdf0e10cSrcweir                         punresolved += 2;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir                     continue;
604cdf0e10cSrcweir                 }
605cdf0e10cSrcweir                 else // a file or directory name may start with '.'
606cdf0e10cSrcweir                 {
607cdf0e10cSrcweir                     if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
608cdf0e10cSrcweir                         return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
609cdf0e10cSrcweir 
610cdf0e10cSrcweir                     ustrchrcat(*punresolved++, path_resolved_so_far);
611cdf0e10cSrcweir 
612cdf0e10cSrcweir                     if ('\0' == *punresolved && !realpath_failed)
613cdf0e10cSrcweir                     {
614cdf0e10cSrcweir                         ferr = _osl_resolvepath(
615cdf0e10cSrcweir                             path_resolved_so_far,
616cdf0e10cSrcweir                             presolvedsf,
617cdf0e10cSrcweir                             &realpath_failed);
618cdf0e10cSrcweir 
619cdf0e10cSrcweir                         if (osl_File_E_None != ferr)
620cdf0e10cSrcweir                             return ferr;
621cdf0e10cSrcweir                     }
622cdf0e10cSrcweir                 }
623cdf0e10cSrcweir             }
624cdf0e10cSrcweir             else if (UNICHAR_SLASH == *punresolved)
625cdf0e10cSrcweir             {
626cdf0e10cSrcweir                 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
627cdf0e10cSrcweir                     return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
628cdf0e10cSrcweir 
629cdf0e10cSrcweir                 ustrchrcat(*punresolved++, path_resolved_so_far);
630cdf0e10cSrcweir 
631cdf0e10cSrcweir                 if (!realpath_failed)
632cdf0e10cSrcweir                 {
633cdf0e10cSrcweir                     ferr = _osl_resolvepath(
634cdf0e10cSrcweir                         path_resolved_so_far,
635cdf0e10cSrcweir                         presolvedsf,
636cdf0e10cSrcweir                         &realpath_failed);
637cdf0e10cSrcweir 
638cdf0e10cSrcweir                     if (osl_File_E_None != ferr)
639cdf0e10cSrcweir                         return ferr;
640cdf0e10cSrcweir 
641cdf0e10cSrcweir                     if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH))
642cdf0e10cSrcweir                     {
643cdf0e10cSrcweir                         if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
644cdf0e10cSrcweir                             return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
645cdf0e10cSrcweir 
646cdf0e10cSrcweir                         ustrchrcat(UNICHAR_SLASH, path_resolved_so_far);
647cdf0e10cSrcweir                     }
648cdf0e10cSrcweir                 }
649cdf0e10cSrcweir             }
650cdf0e10cSrcweir             else // any other character
651cdf0e10cSrcweir             {
652cdf0e10cSrcweir                 if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
653cdf0e10cSrcweir                     return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
654cdf0e10cSrcweir 
655cdf0e10cSrcweir                 ustrchrcat(*punresolved++, path_resolved_so_far);
656cdf0e10cSrcweir 
657cdf0e10cSrcweir                 if ('\0' == *punresolved && !realpath_failed)
658cdf0e10cSrcweir                 {
659cdf0e10cSrcweir                     ferr = _osl_resolvepath(
660cdf0e10cSrcweir                         path_resolved_so_far,
661cdf0e10cSrcweir                         presolvedsf,
662cdf0e10cSrcweir                         &realpath_failed);
663cdf0e10cSrcweir 
664cdf0e10cSrcweir                     if (osl_File_E_None != ferr)
665cdf0e10cSrcweir                         return ferr;
666cdf0e10cSrcweir                 }
667cdf0e10cSrcweir             }
668cdf0e10cSrcweir         }
669cdf0e10cSrcweir 
670cdf0e10cSrcweir         sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
671cdf0e10cSrcweir 
672cdf0e10cSrcweir         OSL_ASSERT(len < PATH_MAX);
673cdf0e10cSrcweir 
674cdf0e10cSrcweir         resolved_path = rtl::OUString(path_resolved_so_far, len);
675cdf0e10cSrcweir 
676cdf0e10cSrcweir         return osl_File_E_None;
677cdf0e10cSrcweir     }
678cdf0e10cSrcweir 
679cdf0e10cSrcweir } // end namespace private
680cdf0e10cSrcweir 
681cdf0e10cSrcweir 
682cdf0e10cSrcweir /******************************************************
683cdf0e10cSrcweir  * osl_getAbsoluteFileURL
684cdf0e10cSrcweir  ******************************************************/
685cdf0e10cSrcweir 
osl_getAbsoluteFileURL(rtl_uString * ustrBaseDirURL,rtl_uString * ustrRelativeURL,rtl_uString ** pustrAbsoluteURL)686cdf0e10cSrcweir oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
687cdf0e10cSrcweir {
688cdf0e10cSrcweir     FileBase::RC  rc;
689cdf0e10cSrcweir     rtl::OUString unresolved_path;
690cdf0e10cSrcweir 
691cdf0e10cSrcweir     rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path);
692cdf0e10cSrcweir 
693cdf0e10cSrcweir     if(FileBase::E_None != rc)
694cdf0e10cSrcweir         return oslFileError(rc);
695cdf0e10cSrcweir 
696cdf0e10cSrcweir     if (systemPathIsRelativePath(unresolved_path))
697cdf0e10cSrcweir     {
698cdf0e10cSrcweir         rtl::OUString base_path;
699cdf0e10cSrcweir         rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False);
700cdf0e10cSrcweir 
701cdf0e10cSrcweir         if (FileBase::E_None != rc)
702cdf0e10cSrcweir             return oslFileError(rc);
703cdf0e10cSrcweir 
704cdf0e10cSrcweir         rtl::OUString abs_path;
705cdf0e10cSrcweir         systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
706cdf0e10cSrcweir 
707cdf0e10cSrcweir         unresolved_path = abs_path;
708cdf0e10cSrcweir     }
709cdf0e10cSrcweir 
710cdf0e10cSrcweir     rtl::OUString resolved_path;
711cdf0e10cSrcweir     rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
712cdf0e10cSrcweir 
713cdf0e10cSrcweir     if (FileBase::E_None == rc)
714cdf0e10cSrcweir     {
715cdf0e10cSrcweir         rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
716cdf0e10cSrcweir         OSL_ASSERT(FileBase::E_None == rc);
717cdf0e10cSrcweir     }
718cdf0e10cSrcweir 
719cdf0e10cSrcweir     return oslFileError(rc);
720cdf0e10cSrcweir }
721cdf0e10cSrcweir 
722cdf0e10cSrcweir 
723cdf0e10cSrcweir namespace /* private */
724cdf0e10cSrcweir {
725cdf0e10cSrcweir 
726cdf0e10cSrcweir     /*********************************************
727cdf0e10cSrcweir      No separate error code if unicode to text
728cdf0e10cSrcweir      conversion or getenv fails because for the
729cdf0e10cSrcweir      caller there is no difference why a file
730cdf0e10cSrcweir      could not be found in $PATH
731cdf0e10cSrcweir      ********************************************/
732cdf0e10cSrcweir 
find_in_PATH(const rtl::OUString & file_path,rtl::OUString & result)733cdf0e10cSrcweir     bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
734cdf0e10cSrcweir     {
735cdf0e10cSrcweir         bool          bfound = false;
736cdf0e10cSrcweir         rtl::OUString path   = rtl::OUString::createFromAscii("PATH");
737cdf0e10cSrcweir         rtl::OUString env_path;
738cdf0e10cSrcweir 
739cdf0e10cSrcweir         if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
740cdf0e10cSrcweir             bfound = osl::searchPath(file_path, env_path, result);
741cdf0e10cSrcweir 
742cdf0e10cSrcweir         return bfound;
743cdf0e10cSrcweir     }
744cdf0e10cSrcweir 
745cdf0e10cSrcweir     /*********************************************
746cdf0e10cSrcweir      No separate error code if unicode to text
747cdf0e10cSrcweir      conversion or getcwd fails because for the
748cdf0e10cSrcweir      caller there is no difference why a file
749cdf0e10cSrcweir      could not be found in CDW
750cdf0e10cSrcweir      ********************************************/
751cdf0e10cSrcweir 
find_in_CWD(const rtl::OUString & file_path,rtl::OUString & result)752cdf0e10cSrcweir     bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
753cdf0e10cSrcweir     {
754cdf0e10cSrcweir         bool bfound = false;
755cdf0e10cSrcweir         rtl::OUString cwd_url;
756cdf0e10cSrcweir 
757cdf0e10cSrcweir         if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
758cdf0e10cSrcweir         {
759cdf0e10cSrcweir             rtl::OUString cwd;
760cdf0e10cSrcweir             FileBase::getSystemPathFromFileURL(cwd_url, cwd);
761cdf0e10cSrcweir             bfound = osl::searchPath(file_path, cwd, result);
762cdf0e10cSrcweir         }
763cdf0e10cSrcweir         return bfound;
764cdf0e10cSrcweir     }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir     /*********************************************
767cdf0e10cSrcweir 
768cdf0e10cSrcweir      ********************************************/
769cdf0e10cSrcweir 
find_in_searchPath(const rtl::OUString & file_path,rtl_uString * search_path,rtl::OUString & result)770cdf0e10cSrcweir     bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
771cdf0e10cSrcweir     {
772cdf0e10cSrcweir         return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
773cdf0e10cSrcweir     }
774cdf0e10cSrcweir 
775cdf0e10cSrcweir } // end namespace private
776cdf0e10cSrcweir 
777cdf0e10cSrcweir 
778cdf0e10cSrcweir /****************************************************************************
779cdf0e10cSrcweir  * osl_searchFileURL
780cdf0e10cSrcweir  ***************************************************************************/
781cdf0e10cSrcweir 
osl_searchFileURL(rtl_uString * ustrFilePath,rtl_uString * ustrSearchPath,rtl_uString ** pustrURL)782cdf0e10cSrcweir oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
783cdf0e10cSrcweir {
784cdf0e10cSrcweir     OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
785cdf0e10cSrcweir 
786cdf0e10cSrcweir     FileBase::RC  rc;
787cdf0e10cSrcweir     rtl::OUString file_path;
788cdf0e10cSrcweir 
789cdf0e10cSrcweir     // try to interpret search path as file url else assume it's a system path list
790cdf0e10cSrcweir     rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
791cdf0e10cSrcweir     if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
792cdf0e10cSrcweir         file_path = ustrFilePath;
793cdf0e10cSrcweir     else if (FileBase::E_None != rc)
794cdf0e10cSrcweir         return oslFileError(rc);
795cdf0e10cSrcweir 
796cdf0e10cSrcweir     bool          bfound = false;
797cdf0e10cSrcweir     rtl::OUString result;
798cdf0e10cSrcweir 
799cdf0e10cSrcweir     if (find_in_searchPath(file_path, ustrSearchPath, result) ||
800cdf0e10cSrcweir         find_in_PATH(file_path, result) ||
801cdf0e10cSrcweir         find_in_CWD(file_path, result))
802cdf0e10cSrcweir     {
803cdf0e10cSrcweir         rtl::OUString resolved;
804cdf0e10cSrcweir 
805cdf0e10cSrcweir         if (osl::realpath(result, resolved))
806cdf0e10cSrcweir         {
807cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
808cdf0e10cSrcweir             oslFileError osl_error =
809cdf0e10cSrcweir #endif
810cdf0e10cSrcweir                 osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
811cdf0e10cSrcweir             OSL_ASSERT(osl_File_E_None == osl_error);
812cdf0e10cSrcweir             bfound = true;
813cdf0e10cSrcweir         }
814cdf0e10cSrcweir     }
815cdf0e10cSrcweir     return bfound ? osl_File_E_None : osl_File_E_NOENT;
816cdf0e10cSrcweir }
817cdf0e10cSrcweir 
818cdf0e10cSrcweir 
819cdf0e10cSrcweir /****************************************************************************
820cdf0e10cSrcweir  * FileURLToPath
821cdf0e10cSrcweir  ***************************************************************************/
822cdf0e10cSrcweir 
FileURLToPath(char * buffer,size_t bufLen,rtl_uString * ustrFileURL)823cdf0e10cSrcweir oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
824cdf0e10cSrcweir {
825cdf0e10cSrcweir     rtl_uString* ustrSystemPath = NULL;
826cdf0e10cSrcweir     oslFileError osl_error      = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
827cdf0e10cSrcweir 
828cdf0e10cSrcweir     if(osl_File_E_None != osl_error)
829cdf0e10cSrcweir         return osl_error;
830cdf0e10cSrcweir 
831cdf0e10cSrcweir     osl_systemPathRemoveSeparator(ustrSystemPath);
832cdf0e10cSrcweir 
833cdf0e10cSrcweir     /* convert unicode path to text */
834cdf0e10cSrcweir     if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
835cdf0e10cSrcweir         osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
836cdf0e10cSrcweir 
837cdf0e10cSrcweir     rtl_uString_release(ustrSystemPath);
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     return osl_error;
840cdf0e10cSrcweir }
841cdf0e10cSrcweir 
842cdf0e10cSrcweir /*****************************************************************************
843cdf0e10cSrcweir  * UnicodeToText
844cdf0e10cSrcweir  ****************************************************************************/
845cdf0e10cSrcweir 
846cdf0e10cSrcweir namespace /* private */
847cdf0e10cSrcweir {
848cdf0e10cSrcweir     class UnicodeToTextConverter_Impl
849cdf0e10cSrcweir     {
850cdf0e10cSrcweir         rtl_UnicodeToTextConverter m_converter;
851cdf0e10cSrcweir 
UnicodeToTextConverter_Impl()852cdf0e10cSrcweir         UnicodeToTextConverter_Impl()
853cdf0e10cSrcweir             : m_converter (rtl_createUnicodeToTextConverter (osl_getThreadTextEncoding()))
854cdf0e10cSrcweir         {}
855cdf0e10cSrcweir 
~UnicodeToTextConverter_Impl()856cdf0e10cSrcweir         ~UnicodeToTextConverter_Impl()
857cdf0e10cSrcweir         {
858cdf0e10cSrcweir             rtl_destroyUnicodeToTextConverter (m_converter);
859cdf0e10cSrcweir         }
860cdf0e10cSrcweir     public:
getInstance()861cdf0e10cSrcweir         static UnicodeToTextConverter_Impl & getInstance()
862cdf0e10cSrcweir         {
863cdf0e10cSrcweir             static UnicodeToTextConverter_Impl g_theConverter;
864cdf0e10cSrcweir             return g_theConverter;
865cdf0e10cSrcweir         }
866cdf0e10cSrcweir 
convert(sal_Unicode const * pSrcBuf,sal_Size nSrcChars,sal_Char * pDstBuf,sal_Size nDstBytes,sal_uInt32 nFlags,sal_uInt32 * pInfo,sal_Size * pSrcCvtChars)867cdf0e10cSrcweir         sal_Size convert(
868cdf0e10cSrcweir             sal_Unicode const * pSrcBuf, sal_Size nSrcChars, sal_Char * pDstBuf, sal_Size nDstBytes,
869cdf0e10cSrcweir             sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtChars)
870cdf0e10cSrcweir         {
871cdf0e10cSrcweir             OSL_ASSERT(m_converter != 0);
872cdf0e10cSrcweir             return rtl_convertUnicodeToText (
873cdf0e10cSrcweir                 m_converter, 0, pSrcBuf, nSrcChars, pDstBuf, nDstBytes, nFlags, pInfo, pSrcCvtChars);
874cdf0e10cSrcweir         }
875cdf0e10cSrcweir     };
876cdf0e10cSrcweir } // end namespace private
877cdf0e10cSrcweir 
UnicodeToText(char * buffer,size_t bufLen,const sal_Unicode * uniText,sal_Int32 uniTextLen)878cdf0e10cSrcweir int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
879cdf0e10cSrcweir {
880cdf0e10cSrcweir     sal_uInt32   nInfo = 0;
881cdf0e10cSrcweir     sal_Size     nSrcChars = 0;
882cdf0e10cSrcweir 
883cdf0e10cSrcweir     sal_Size nDestBytes = UnicodeToTextConverter_Impl::getInstance().convert (
884cdf0e10cSrcweir         uniText, uniTextLen, buffer, bufLen,
885cdf0e10cSrcweir         OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, &nInfo, &nSrcChars);
886cdf0e10cSrcweir 
887cdf0e10cSrcweir     if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
888cdf0e10cSrcweir     {
889cdf0e10cSrcweir         errno = EOVERFLOW;
890cdf0e10cSrcweir         return 0;
891cdf0e10cSrcweir     }
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     /* ensure trailing '\0' */
894cdf0e10cSrcweir     buffer[nDestBytes] = '\0';
895cdf0e10cSrcweir     return nDestBytes;
896cdf0e10cSrcweir }
897cdf0e10cSrcweir 
898cdf0e10cSrcweir /*****************************************************************************
899cdf0e10cSrcweir  * TextToUnicode
900cdf0e10cSrcweir  ****************************************************************************/
901cdf0e10cSrcweir 
902cdf0e10cSrcweir namespace /* private */
903cdf0e10cSrcweir {
904cdf0e10cSrcweir     class TextToUnicodeConverter_Impl
905cdf0e10cSrcweir     {
906cdf0e10cSrcweir         rtl_TextToUnicodeConverter m_converter;
907cdf0e10cSrcweir 
TextToUnicodeConverter_Impl()908cdf0e10cSrcweir         TextToUnicodeConverter_Impl()
909cdf0e10cSrcweir             : m_converter (rtl_createTextToUnicodeConverter (osl_getThreadTextEncoding()))
910cdf0e10cSrcweir         {}
911cdf0e10cSrcweir 
~TextToUnicodeConverter_Impl()912cdf0e10cSrcweir         ~TextToUnicodeConverter_Impl()
913cdf0e10cSrcweir         {
914cdf0e10cSrcweir             rtl_destroyTextToUnicodeConverter (m_converter);
915cdf0e10cSrcweir         }
916cdf0e10cSrcweir 
917cdf0e10cSrcweir     public:
getInstance()918cdf0e10cSrcweir         static TextToUnicodeConverter_Impl & getInstance()
919cdf0e10cSrcweir         {
920cdf0e10cSrcweir             static TextToUnicodeConverter_Impl g_theConverter;
921cdf0e10cSrcweir             return g_theConverter;
922cdf0e10cSrcweir         }
923cdf0e10cSrcweir 
convert(sal_Char const * pSrcBuf,sal_Size nSrcBytes,sal_Unicode * pDstBuf,sal_Size nDstChars,sal_uInt32 nFlags,sal_uInt32 * pInfo,sal_Size * pSrcCvtBytes)924cdf0e10cSrcweir         sal_Size convert(
925cdf0e10cSrcweir             sal_Char const * pSrcBuf, sal_Size nSrcBytes, sal_Unicode * pDstBuf, sal_Size nDstChars,
926cdf0e10cSrcweir             sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtBytes)
927cdf0e10cSrcweir         {
928cdf0e10cSrcweir             OSL_ASSERT(m_converter != 0);
929cdf0e10cSrcweir             return rtl_convertTextToUnicode (
930cdf0e10cSrcweir                 m_converter, 0, pSrcBuf, nSrcBytes, pDstBuf, nDstChars, nFlags, pInfo, pSrcCvtBytes);
931cdf0e10cSrcweir         }
932cdf0e10cSrcweir     };
933cdf0e10cSrcweir } // end namespace private
934cdf0e10cSrcweir 
TextToUnicode(const char * text,size_t text_buffer_size,sal_Unicode * unic_text,sal_Int32 unic_text_buffer_size)935cdf0e10cSrcweir int TextToUnicode(
936cdf0e10cSrcweir     const char*  text,
937cdf0e10cSrcweir     size_t       text_buffer_size,
938cdf0e10cSrcweir     sal_Unicode* unic_text,
939cdf0e10cSrcweir     sal_Int32    unic_text_buffer_size)
940cdf0e10cSrcweir {
941cdf0e10cSrcweir     sal_uInt32 nInfo = 0;
942cdf0e10cSrcweir     sal_Size   nSrcChars = 0;
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     sal_Size nDestBytes = TextToUnicodeConverter_Impl::getInstance().convert(
945cdf0e10cSrcweir         text,  text_buffer_size, unic_text, unic_text_buffer_size,
946cdf0e10cSrcweir         OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, &nInfo, &nSrcChars);
947cdf0e10cSrcweir 
948cdf0e10cSrcweir     if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
949cdf0e10cSrcweir     {
950cdf0e10cSrcweir         errno = EOVERFLOW;
951cdf0e10cSrcweir         return 0;
952cdf0e10cSrcweir     }
953cdf0e10cSrcweir 
954cdf0e10cSrcweir     /* ensure trailing '\0' */
955cdf0e10cSrcweir     unic_text[nDestBytes] = '\0';
956cdf0e10cSrcweir     return nDestBytes;
957cdf0e10cSrcweir }
958