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