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