1*c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*c82f2877SAndrew Rist  * distributed with this work for additional information
6*c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9*c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*c82f2877SAndrew Rist  *
11*c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*c82f2877SAndrew Rist  *
13*c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15*c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17*c82f2877SAndrew Rist  * specific language governing permissions and limitations
18*c82f2877SAndrew Rist  * under the License.
19*c82f2877SAndrew Rist  *
20*c82f2877SAndrew Rist  *************************************************************/
21*c82f2877SAndrew Rist 
22*c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <cstring>
28cdf0e10cSrcweir #include <sys/stat.h>
29cdf0e10cSrcweir #include <unistd.h>
30cdf0e10cSrcweir #include <limits.h>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include "vcl/helper.hxx"
33cdf0e10cSrcweir #include "vcl/ppdparser.hxx"
34cdf0e10cSrcweir #include "tools/string.hxx"
35cdf0e10cSrcweir #include "tools/urlobj.hxx"
36cdf0e10cSrcweir #include "osl/file.hxx"
37cdf0e10cSrcweir #include "osl/process.h"
38cdf0e10cSrcweir #include "rtl/bootstrap.hxx"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir using namespace rtl;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir namespace psp {
43cdf0e10cSrcweir 
44cdf0e10cSrcweir OUString getOfficePath( enum whichOfficePath ePath )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir     static OUString aNetPath;
47cdf0e10cSrcweir     static OUString aUserPath;
48cdf0e10cSrcweir     static OUString aConfigPath;
49cdf0e10cSrcweir     static OUString aEmpty;
50cdf0e10cSrcweir     static bool bOnce = false;
51cdf0e10cSrcweir 
52cdf0e10cSrcweir     if( ! bOnce )
53cdf0e10cSrcweir     {
54cdf0e10cSrcweir         bOnce = true;
55cdf0e10cSrcweir         OUString aIni;
56cdf0e10cSrcweir         Bootstrap::get( OUString( RTL_CONSTASCII_USTRINGPARAM( "BRAND_BASE_DIR" ) ), aIni );
57cdf0e10cSrcweir         aIni += OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/" SAL_CONFIGFILE( "bootstrap" ) ) );
58cdf0e10cSrcweir         Bootstrap aBootstrap( aIni );
59cdf0e10cSrcweir         aBootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "CustomDataUrl" ) ), aConfigPath );
60cdf0e10cSrcweir         aBootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseInstallation" ) ), aNetPath );
61cdf0e10cSrcweir         aBootstrap.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "UserInstallation" ) ), aUserPath );
62cdf0e10cSrcweir         OUString aUPath = aUserPath;
63cdf0e10cSrcweir 
64cdf0e10cSrcweir         if( ! aConfigPath.compareToAscii( "file://", 7 ) )
65cdf0e10cSrcweir         {
66cdf0e10cSrcweir             OUString aSysPath;
67cdf0e10cSrcweir             if( osl_getSystemPathFromFileURL( aConfigPath.pData, &aSysPath.pData ) == osl_File_E_None )
68cdf0e10cSrcweir                 aConfigPath = aSysPath;
69cdf0e10cSrcweir         }
70cdf0e10cSrcweir         if( ! aNetPath.compareToAscii( "file://", 7 ) )
71cdf0e10cSrcweir         {
72cdf0e10cSrcweir             OUString aSysPath;
73cdf0e10cSrcweir             if( osl_getSystemPathFromFileURL( aNetPath.pData, &aSysPath.pData ) == osl_File_E_None )
74cdf0e10cSrcweir                 aNetPath = aSysPath;
75cdf0e10cSrcweir         }
76cdf0e10cSrcweir         if( ! aUserPath.compareToAscii( "file://", 7 ) )
77cdf0e10cSrcweir         {
78cdf0e10cSrcweir             OUString aSysPath;
79cdf0e10cSrcweir             if( osl_getSystemPathFromFileURL( aUserPath.pData, &aSysPath.pData ) == osl_File_E_None )
80cdf0e10cSrcweir                 aUserPath = aSysPath;
81cdf0e10cSrcweir         }
82cdf0e10cSrcweir         // ensure user path exists
83cdf0e10cSrcweir         aUPath += OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/psprint" ) );
84cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
85cdf0e10cSrcweir         oslFileError eErr =
86cdf0e10cSrcweir         #endif
87cdf0e10cSrcweir         osl_createDirectoryPath( aUPath.pData, NULL, NULL );
88cdf0e10cSrcweir         #if OSL_DEBUG_LEVEL > 1
89cdf0e10cSrcweir         fprintf( stderr, "try to create \"%s\" = %d\n", OUStringToOString( aUPath, RTL_TEXTENCODING_UTF8 ).getStr(), eErr );
90cdf0e10cSrcweir         #endif
91cdf0e10cSrcweir     }
92cdf0e10cSrcweir 
93cdf0e10cSrcweir     switch( ePath )
94cdf0e10cSrcweir     {
95cdf0e10cSrcweir         case ConfigPath: return aConfigPath;
96cdf0e10cSrcweir         case NetPath: return aNetPath;
97cdf0e10cSrcweir         case UserPath: return aUserPath;
98cdf0e10cSrcweir     }
99cdf0e10cSrcweir     return aEmpty;
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
102cdf0e10cSrcweir static OString getEnvironmentPath( const char* pKey )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir     OString aPath;
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     const char* pValue = getenv( pKey );
107cdf0e10cSrcweir     if( pValue && *pValue )
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         aPath = OString( pValue );
110cdf0e10cSrcweir     }
111cdf0e10cSrcweir     return aPath;
112cdf0e10cSrcweir }
113cdf0e10cSrcweir 
114cdf0e10cSrcweir } // namespace psp
115cdf0e10cSrcweir 
116cdf0e10cSrcweir void psp::getPrinterPathList( std::list< OUString >& rPathList, const char* pSubDir )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     rPathList.clear();
119cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     OUStringBuffer aPathBuffer( 256 );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     // append net path
124cdf0e10cSrcweir     aPathBuffer.append( getOfficePath( psp::NetPath ) );
125cdf0e10cSrcweir     if( aPathBuffer.getLength() )
126cdf0e10cSrcweir     {
127cdf0e10cSrcweir         aPathBuffer.appendAscii( "/share/psprint" );
128cdf0e10cSrcweir         if( pSubDir )
129cdf0e10cSrcweir         {
130cdf0e10cSrcweir             aPathBuffer.append( sal_Unicode('/') );
131cdf0e10cSrcweir             aPathBuffer.appendAscii( pSubDir );
132cdf0e10cSrcweir         }
133cdf0e10cSrcweir         rPathList.push_back( aPathBuffer.makeStringAndClear() );
134cdf0e10cSrcweir     }
135cdf0e10cSrcweir     // append user path
136cdf0e10cSrcweir     aPathBuffer.append( getOfficePath( psp::UserPath ) );
137cdf0e10cSrcweir     if( aPathBuffer.getLength() )
138cdf0e10cSrcweir     {
139cdf0e10cSrcweir         aPathBuffer.appendAscii( "/user/psprint" );
140cdf0e10cSrcweir         if( pSubDir )
141cdf0e10cSrcweir         {
142cdf0e10cSrcweir             aPathBuffer.append( sal_Unicode('/') );
143cdf0e10cSrcweir             aPathBuffer.appendAscii( pSubDir );
144cdf0e10cSrcweir         }
145cdf0e10cSrcweir         rPathList.push_back( aPathBuffer.makeStringAndClear() );
146cdf0e10cSrcweir     }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir     OString aPath( getEnvironmentPath("SAL_PSPRINT") );
149cdf0e10cSrcweir     sal_Int32 nIndex = 0;
150cdf0e10cSrcweir     do
151cdf0e10cSrcweir     {
152cdf0e10cSrcweir         OString aDir( aPath.getToken( 0, ':', nIndex ) );
153cdf0e10cSrcweir         if( ! aDir.getLength() )
154cdf0e10cSrcweir             continue;
155cdf0e10cSrcweir 
156cdf0e10cSrcweir         if( pSubDir )
157cdf0e10cSrcweir         {
158cdf0e10cSrcweir             aDir += "/";
159cdf0e10cSrcweir             aDir += pSubDir;
160cdf0e10cSrcweir         }
161cdf0e10cSrcweir         struct stat aStat;
162cdf0e10cSrcweir         if( stat( aDir.getStr(), &aStat ) || ! S_ISDIR( aStat.st_mode ) )
163cdf0e10cSrcweir             continue;
164cdf0e10cSrcweir 
165cdf0e10cSrcweir         rPathList.push_back( OStringToOUString( aDir, aEncoding ) );
166cdf0e10cSrcweir     } while( nIndex != -1 );
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     #ifdef SYSTEM_PPD_DIR
169cdf0e10cSrcweir     if( pSubDir && rtl_str_compare( pSubDir, PRINTER_PPDDIR ) == 0 )
170cdf0e10cSrcweir     {
171cdf0e10cSrcweir         rPathList.push_back( rtl::OStringToOUString( rtl::OString( SYSTEM_PPD_DIR ), RTL_TEXTENCODING_UTF8 ) );
172cdf0e10cSrcweir     }
173cdf0e10cSrcweir     #endif
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     if( rPathList.empty() )
176cdf0e10cSrcweir     {
177cdf0e10cSrcweir         // last resort: next to program file (mainly for setup)
178cdf0e10cSrcweir         OUString aExe;
179cdf0e10cSrcweir         if( osl_getExecutableFile( &aExe.pData ) == osl_Process_E_None )
180cdf0e10cSrcweir         {
181cdf0e10cSrcweir             INetURLObject aDir( aExe );
182cdf0e10cSrcweir             aDir.removeSegment();
183cdf0e10cSrcweir             aExe = aDir.GetMainURL( INetURLObject::NO_DECODE );
184cdf0e10cSrcweir             OUString aSysPath;
185cdf0e10cSrcweir             if( osl_getSystemPathFromFileURL( aExe.pData, &aSysPath.pData ) == osl_File_E_None )
186cdf0e10cSrcweir             {
187cdf0e10cSrcweir                 rPathList.push_back( aSysPath );
188cdf0e10cSrcweir             }
189cdf0e10cSrcweir         }
190cdf0e10cSrcweir     }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir OUString psp::getFontPath()
194cdf0e10cSrcweir {
195cdf0e10cSrcweir     static OUString aPath;
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     if( ! aPath.getLength() )
198cdf0e10cSrcweir     {
199cdf0e10cSrcweir         OUStringBuffer aPathBuffer( 512 );
200cdf0e10cSrcweir 
201cdf0e10cSrcweir         OUString aConfigPath( getOfficePath( psp::ConfigPath ) );
202cdf0e10cSrcweir         OUString aNetPath( getOfficePath( psp::NetPath ) );
203cdf0e10cSrcweir         OUString aUserPath( getOfficePath( psp::UserPath ) );
204cdf0e10cSrcweir         if( aConfigPath.getLength() )
205cdf0e10cSrcweir         {
206cdf0e10cSrcweir             // #i53530# Path from CustomDataUrl will completely
207cdf0e10cSrcweir             // replace net and user paths if the path exists
208cdf0e10cSrcweir             aPathBuffer.append(aConfigPath);
209cdf0e10cSrcweir             aPathBuffer.appendAscii("/share/fonts");
210cdf0e10cSrcweir             // check existance of config path
211cdf0e10cSrcweir             struct stat aStat;
212cdf0e10cSrcweir             if( 0 != stat( OUStringToOString( aPathBuffer.makeStringAndClear(), osl_getThreadTextEncoding() ).getStr(), &aStat )
213cdf0e10cSrcweir                 || ! S_ISDIR( aStat.st_mode ) )
214cdf0e10cSrcweir                 aConfigPath = OUString();
215cdf0e10cSrcweir             else
216cdf0e10cSrcweir             {
217cdf0e10cSrcweir                 aPathBuffer.append(aConfigPath);
218cdf0e10cSrcweir                 aPathBuffer.appendAscii("/share/fonts");
219cdf0e10cSrcweir             }
220cdf0e10cSrcweir         }
221cdf0e10cSrcweir         if( aConfigPath.getLength() == 0 )
222cdf0e10cSrcweir         {
223cdf0e10cSrcweir             if( aNetPath.getLength() )
224cdf0e10cSrcweir             {
225cdf0e10cSrcweir                 aPathBuffer.append( aNetPath );
226cdf0e10cSrcweir                 aPathBuffer.appendAscii( "/share/fonts/truetype;");
227cdf0e10cSrcweir                 aPathBuffer.append( aNetPath );
228cdf0e10cSrcweir                 aPathBuffer.appendAscii( "/share/fonts/type1;" );
229cdf0e10cSrcweir             }
230cdf0e10cSrcweir             if( aUserPath.getLength() )
231cdf0e10cSrcweir             {
232cdf0e10cSrcweir                 aPathBuffer.append( aUserPath );
233cdf0e10cSrcweir                 aPathBuffer.appendAscii( "/user/fonts" );
234cdf0e10cSrcweir             }
235cdf0e10cSrcweir         }
236cdf0e10cSrcweir         OString aEnvPath( getEnvironmentPath( "SAL_FONTPATH_PRIVATE" ) );
237cdf0e10cSrcweir         if( aEnvPath.getLength() )
238cdf0e10cSrcweir         {
239cdf0e10cSrcweir             aPathBuffer.append( sal_Unicode(';') );
240cdf0e10cSrcweir             aPathBuffer.append( OStringToOUString( aEnvPath, osl_getThreadTextEncoding() ) );
241cdf0e10cSrcweir         }
242cdf0e10cSrcweir 
243cdf0e10cSrcweir         aPath = aPathBuffer.makeStringAndClear();
244cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
245cdf0e10cSrcweir         fprintf( stderr, "initializing font path to \"%s\"\n", OUStringToOString( aPath, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
246cdf0e10cSrcweir #endif
247cdf0e10cSrcweir     }
248cdf0e10cSrcweir     return aPath;
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir bool psp::convertPfbToPfa( ::osl::File& rInFile, ::osl::File& rOutFile )
252cdf0e10cSrcweir {
253cdf0e10cSrcweir     static unsigned char hexDigits[] =
254cdf0e10cSrcweir         {
255cdf0e10cSrcweir             '0', '1', '2', '3', '4', '5', '6', '7',
256cdf0e10cSrcweir             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
257cdf0e10cSrcweir         };
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     bool bSuccess = true;
260cdf0e10cSrcweir     bool bEof = false;
261cdf0e10cSrcweir     unsigned char buffer[256];
262cdf0e10cSrcweir     sal_uInt64 nRead;
263cdf0e10cSrcweir     sal_uInt64 nOrgPos = 0;
264cdf0e10cSrcweir     rInFile.getPos( nOrgPos );
265cdf0e10cSrcweir 
266cdf0e10cSrcweir     while( bSuccess && ! bEof )
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         // read leading bytes
269cdf0e10cSrcweir         bEof = ! rInFile.read( buffer, 6, nRead ) && nRead == 6 ? false : true;
270cdf0e10cSrcweir         unsigned int nType = buffer[ 1 ];
271cdf0e10cSrcweir         unsigned int nBytesToRead = buffer[2] | buffer[3] << 8 | buffer[4] << 16 | buffer[5] << 24;
272cdf0e10cSrcweir         if( buffer[0] != 0x80 ) // test for pfb m_agic number
273cdf0e10cSrcweir         {
274cdf0e10cSrcweir             // this migt be a pfa font already
275cdf0e10cSrcweir             sal_uInt64 nWrite = 0;
276cdf0e10cSrcweir             if( ! rInFile.read( buffer+6, 9, nRead ) && nRead == 9 &&
277cdf0e10cSrcweir                 ( ! std::strncmp( (char*)buffer, "%!FontType1-", 12 ) ||
278cdf0e10cSrcweir                   ! std::strncmp( (char*)buffer, "%!PS-AdobeFont-", 15 ) ) )
279cdf0e10cSrcweir             {
280cdf0e10cSrcweir                 if( rOutFile.write( buffer, 15, nWrite ) || nWrite != 15 )
281cdf0e10cSrcweir                     bSuccess = false;
282cdf0e10cSrcweir                 while( bSuccess &&
283cdf0e10cSrcweir                        ! rInFile.read( buffer, sizeof( buffer ), nRead ) &&
284cdf0e10cSrcweir                        nRead != 0 )
285cdf0e10cSrcweir                 {
286cdf0e10cSrcweir                     if( rOutFile.write( buffer, nRead, nWrite ) ||
287cdf0e10cSrcweir                         nWrite != nRead )
288cdf0e10cSrcweir                         bSuccess = false;
289cdf0e10cSrcweir                 }
290cdf0e10cSrcweir                 bEof = true;
291cdf0e10cSrcweir             }
292cdf0e10cSrcweir             else
293cdf0e10cSrcweir                 bSuccess = false;
294cdf0e10cSrcweir         }
295cdf0e10cSrcweir         else if( nType == 1 || nType == 2 )
296cdf0e10cSrcweir         {
297cdf0e10cSrcweir             unsigned char* pBuffer = new unsigned char[ nBytesToRead+1 ];
298cdf0e10cSrcweir 
299cdf0e10cSrcweir             if( ! rInFile.read( pBuffer, nBytesToRead, nRead ) && nRead == nBytesToRead )
300cdf0e10cSrcweir             {
301cdf0e10cSrcweir                 if( nType == 1 )
302cdf0e10cSrcweir                 {
303cdf0e10cSrcweir                     // ascii data, convert dos lineends( \r\n ) and
304cdf0e10cSrcweir                     // m_ac lineends( \r ) to \n
305cdf0e10cSrcweir                     unsigned char * pWriteBuffer = new unsigned char[ nBytesToRead ];
306cdf0e10cSrcweir                     unsigned int nBytesToWrite = 0;
307cdf0e10cSrcweir                     for( unsigned int i = 0; i < nBytesToRead; i++ )
308cdf0e10cSrcweir                     {
309cdf0e10cSrcweir                         if( pBuffer[i] != '\r' )
310cdf0e10cSrcweir                             pWriteBuffer[ nBytesToWrite++ ] = pBuffer[i];
311cdf0e10cSrcweir                         else if( pBuffer[ i+1 ] == '\n' )
312cdf0e10cSrcweir                         {
313cdf0e10cSrcweir                             i++;
314cdf0e10cSrcweir                             pWriteBuffer[ nBytesToWrite++ ] = '\n';
315cdf0e10cSrcweir                         }
316cdf0e10cSrcweir                         else
317cdf0e10cSrcweir                             pWriteBuffer[ nBytesToWrite++ ] = '\n';
318cdf0e10cSrcweir                     }
319cdf0e10cSrcweir                     if( rOutFile.write( pWriteBuffer, nBytesToWrite, nRead ) || nRead != nBytesToWrite )
320cdf0e10cSrcweir                         bSuccess = false;
321cdf0e10cSrcweir 
322cdf0e10cSrcweir                     delete [] pWriteBuffer;
323cdf0e10cSrcweir                 }
324cdf0e10cSrcweir                 else
325cdf0e10cSrcweir                 {
326cdf0e10cSrcweir                     // binary data
327cdf0e10cSrcweir                     unsigned int nBuffer = 0;
328cdf0e10cSrcweir                     for( unsigned int i = 0; i < nBytesToRead && bSuccess; i++ )
329cdf0e10cSrcweir                     {
330cdf0e10cSrcweir                         buffer[ nBuffer++ ] = hexDigits[ pBuffer[ i ] >> 4 ];
331cdf0e10cSrcweir                         buffer[ nBuffer++ ] = hexDigits[ pBuffer[ i ] & 15 ];
332cdf0e10cSrcweir                         if( nBuffer >= 80 )
333cdf0e10cSrcweir                         {
334cdf0e10cSrcweir                             buffer[ nBuffer++ ] = '\n';
335cdf0e10cSrcweir                             if( rOutFile.write( buffer, nBuffer, nRead ) || nRead != nBuffer )
336cdf0e10cSrcweir                                 bSuccess = false;
337cdf0e10cSrcweir                             nBuffer = 0;
338cdf0e10cSrcweir                         }
339cdf0e10cSrcweir                     }
340cdf0e10cSrcweir                     if( nBuffer > 0 && bSuccess )
341cdf0e10cSrcweir                     {
342cdf0e10cSrcweir                         buffer[ nBuffer++ ] = '\n';
343cdf0e10cSrcweir                         if( rOutFile.write( buffer, nBuffer, nRead ) || nRead != nBuffer )
344cdf0e10cSrcweir                             bSuccess = false;
345cdf0e10cSrcweir                     }
346cdf0e10cSrcweir                 }
347cdf0e10cSrcweir             }
348cdf0e10cSrcweir             else
349cdf0e10cSrcweir                 bSuccess = false;
350cdf0e10cSrcweir 
351cdf0e10cSrcweir             delete [] pBuffer;
352cdf0e10cSrcweir         }
353cdf0e10cSrcweir         else if( nType == 3 )
354cdf0e10cSrcweir             bEof = true;
355cdf0e10cSrcweir         else
356cdf0e10cSrcweir             bSuccess = false;
357cdf0e10cSrcweir     }
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     return bSuccess;
360cdf0e10cSrcweir }
361cdf0e10cSrcweir 
362cdf0e10cSrcweir void psp::normPath( OString& rPath )
363cdf0e10cSrcweir {
364cdf0e10cSrcweir     char buf[PATH_MAX];
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     ByteString aPath( rPath );
367cdf0e10cSrcweir 
368cdf0e10cSrcweir     // double slashes and slash at end are probably
369cdf0e10cSrcweir     // removed by realpath anyway, but since this runs
370cdf0e10cSrcweir     // on many different platforms let's play it safe
371cdf0e10cSrcweir     while( aPath.SearchAndReplace( "//", "/" ) != STRING_NOTFOUND )
372cdf0e10cSrcweir         ;
373cdf0e10cSrcweir     if( aPath.Len() > 0 && aPath.GetChar( aPath.Len()-1 ) == '/' )
374cdf0e10cSrcweir         aPath.Erase( aPath.Len()-1 );
375cdf0e10cSrcweir 
376cdf0e10cSrcweir     if( ( aPath.Search( "./" ) != STRING_NOTFOUND ||
377cdf0e10cSrcweir 		  aPath.Search( "~" ) != STRING_NOTFOUND )
378cdf0e10cSrcweir         && realpath( aPath.GetBuffer(), buf ) )
379cdf0e10cSrcweir     {
380cdf0e10cSrcweir         rPath = buf;
381cdf0e10cSrcweir     }
382cdf0e10cSrcweir     else
383cdf0e10cSrcweir     {
384cdf0e10cSrcweir         rPath = aPath;
385cdf0e10cSrcweir     }
386cdf0e10cSrcweir }
387cdf0e10cSrcweir 
388cdf0e10cSrcweir void psp::splitPath( OString& rPath, OString& rDir, OString& rBase )
389cdf0e10cSrcweir {
390cdf0e10cSrcweir     normPath( rPath );
391cdf0e10cSrcweir     sal_Int32 nIndex = rPath.lastIndexOf( '/' );
392cdf0e10cSrcweir     if( nIndex > 0 )
393cdf0e10cSrcweir         rDir = rPath.copy( 0, nIndex );
394cdf0e10cSrcweir     else if( nIndex == 0 ) // root dir
395cdf0e10cSrcweir         rDir = rPath.copy( 0, 1 );
396cdf0e10cSrcweir     if( rPath.getLength() > nIndex+1 )
397cdf0e10cSrcweir         rBase = rPath.copy( nIndex+1 );
398cdf0e10cSrcweir }
399cdf0e10cSrcweir 
400cdf0e10cSrcweir 
401